javascript - 在数组中组合相似的兄弟姐妹
问题描述
我有一个对象列表,我需要根据给定的标准合并相似的兄弟姐妹。关键是限制表中显示的相似行数。
以这种情况为例:
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;
并且可以通过调整from
andto
字段来合并它们:
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];
// ??
}
一些澄清:
- 依赖
combineFn
和similarFn
是中心,因为哪些行被认为是相似的标准,以及如何合并相似的行,将因数据集而异。 - 是共享的
subject
,也可能在其他地方使用/显示,因此不应“弄乱”原始数组和对象。可以传递来自的对象items
,但不能更改任何值,并且items
数组应保持不变(相同的项目数,相同的顺序)。
抱歉,我之前没有正确/根本没有提到这些要点,因为它们确实改变了很多问题......
解决方案
您可以遍历数据,并跟踪“当前”百分比值。如果不同,则创建一个新对象(项目的副本),并将其推送到结果数组中。相同时,只需更新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);
使用similar
和combine
函数
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);