首页 > 解决方案 > 在数组中组合相似的兄弟姐妹

问题描述

我有一个对象列表,我需要根据给定的标准合并相似的兄弟姐妹。关键是限制表中显示的相似行数。

以这种情况为例:

const items = [
  { from: 0,  to: 2,  percent: 70 },
  { from: 2,  to: 4,  percent: 70 },
  { from: 4,  to: 7,  percent: 70 },
  { from: 7,  to: 8,  percent: 50 },
  { from: 8,  to: 9,  percent: 70 },
  { from: 9,  to: 10, percent: 70 },
  { from: 10, to: 13, percent: 30 },
];

在这里,应该合并的相似行是具有相同百分比的行:

const similar = (a, b) => a.percent == b.percent;

并且可以通过调整fromandto字段来合并它们:

const combine = (...items) => ({
    from: items[0].from,
    to: items[items.length - 1].to,
    percent: items[0].percent,
})

结果应该是:

const combined = combineSimilar(items, combine, similar);
[
  { from: 0,  to: 7,  percent: 70 }, // 0, 1, 2 merged
  { from: 7,  to: 8,  percent: 50 }, // 3 as is
  { from: 8,  to: 10, percent: 70 }, // 4, 5 merged
  { from: 10, to: 13, percent: 30 }, // 6 as is
];

我“看到”需要做什么,但是在将其归结为实际算法时遇到了问题。尝试谷歌搜索,但我能找到的只是完整列表中重复项的算法,而不仅仅是在兄弟姐妹中,并且删除重复项而不是组合它们。

也许这种算法只是被称为不同于我正在寻找的东西?

谁能帮我实现这个?即如何完成以下功能?

function combineSimilar<T>(
  subject: T[],
  combineFn: (...items: T[]) => T,
  similarFn: (a: T, b: T) => boolean
) {
  if(subject.length < 2) return [...subject];

  // ??
}

一些澄清:

抱歉,我之前没有正确/根本没有提到这些要点,因为它们确实改变了很多问题......

标签: javascriptarraysalgorithm

解决方案


您可以遍历数据,并跟踪“当前”百分比值。如果不同,则创建一个新对象(项目的副本),并将其推送到结果数组中。相同时,只需更新to最后创建的对象中的字段即可。

from从您的问题中不清楚,但如果该值与以前的to值不同(代表一个差距),也许您还想从一个新对象开始。我还实现了:

function combineSimilar(items) {
    // Optionally sort by `from` if not already done
    items.sort((a,b) => a.from - b.from);
    let result = [], curr = {};
    for (let item of items) {
        if (item.percent != curr.percent || item.from > curr.to) {
            result.push(curr = {...item});
        }
        curr.to = item.to;
    }
    return result;
}

const items = [
  { from: 0,  to: 2,  percent: 70 },
  { from: 2,  to: 4,  percent: 70 },
  { from: 4,  to: 7,  percent: 70 },
  { from: 7,  to: 8,  percent: 50 },
  { from: 8,  to: 9,  percent: 70 },
  { from: 9,  to: 10, percent: 70 },
  { from: 10, to: 13, percent: 30 },
];
let result = combineSimilar(items);
console.log(result);

使用similarcombine函数

const similar = (a, b) => a.percent == b.percent;

const combine = (...items) => ({
    ...items[0],
    to: items[items.length - 1].to
});

function combineSimilar(items, similar, combine) {
    // Optionally sort by `from` if not already done
    items.sort((a,b) => a.from - b.from);
    let result = [], curr = {};
    for (let item of items) {
        if (!similar(item, curr)) result.push(curr = {...item});
        Object.assign(curr, combine(curr, item));
    }
    return result;
}

const items = [
  { from: 0,  to: 2,  percent: 70 },
  { from: 2,  to: 4,  percent: 70 },
  { from: 4,  to: 7,  percent: 70 },
  { from: 7,  to: 8,  percent: 50 },
  { from: 8,  to: 9,  percent: 70 },
  { from: 9,  to: 10, percent: 70 },
  { from: 10, to: 13, percent: 30 },
];
let result = combineSimilar(items, similar, combine);
console.log(result);


推荐阅读