如何实现同Unit下同Reference保留最长Duration的数组过滤?
问题需求
当数组元素属于同一个unit且拥有相同reference时,移除其余元素,仅保留duration时长最长的元素。
原始数组
const array = [ { reference: 'Tet our mission not here', duration: { start: '2:33.213', end: '2:35.871' }, unit: 21, }, { reference: 'Tet our mission', duration: { start: '2:33.213', end: '2:35.871' }, unit: 22, }, { reference: 'we built the Tet our mission control', duration: { start: '2:10.000', end: '2:40.403' }, unit: 23, }, { reference: 'we built the Tet our mission control', duration: { start: '2:40.000', end: '2:40.403' }, unit: 23, }, { reference: 'we built the Tet', duration: { start: '2:37.345', end: '2:38.500' }, unit: 23, }, { reference: 'we built the Tet our mission control', duration: { start: '2:30.000', end: '2:40.403' }, unit: 23, } ];
现有问题代码
const array = [ { reference: 'Tet our mission not here', duration: { start: '2:33.213', end: '2:35.871' }, unit: 21, }, { reference: 'Tet our mission', duration: { start: '2:33.213', end: '2:35.871' }, unit: 22, }, { reference: 'we built the Tet our mission control', duration: { start: '2:10.000', end: '2:40.403' }, unit: 23, }, { reference: 'we built the Tet our mission control', duration: { start: '2:40.000', end: '2:40.403' }, unit: 23, }, { reference: 'we built the Tet', duration: { start: '2:37.345', end: '2:38.500' }, unit: 23, }, { reference: 'we built the Tet our mission control', duration: { start: '2:30.000', end: '2:40.403' }, unit: 23, } ]; console.log(getLongestByUnit(array)) function getLongestByUnit(array) { const by_unit = {}; array.forEach(el => { let old = by_unit[el.unit] if (!old) { by_unit[el.unit] = el; } else if (el.reference == old.reference && (getSecondsDuration(el.duration.start, el.duration.end) > getSecondsDuration(old.duration.start, old.duration.end))) { by_unit[el.unit] = el; } else { by_unit[el.unit] = el; } }); let result = Object.values(by_unit); return result; } function getSecondsDuration(start, end) { const milisecondsDiff = (hrsToSecs(end) * 1000) - (hrsToSecs(start) * 1000); return milisecondsDiff / 1000; } function hrsToSecs(hrs) { var b = hrs.split(':'); return b.length > 2 ? b[0] * 3600 + b[1] * 60 + +b[2] : b[0] * 60 + +b[1]; }
期望输出
[ { reference: 'Tet our mission not here', duration: { start: '2:33.213', end: '2:35.871' }, unit: 21, }, { reference: 'Tet our mission', duration: { start: '2:33.213', end: '2:35.871' }, unit: 22, }, { // 此元素时长最长 reference: 'we built the Tet our mission control', duration: { start: '2:10.000', end: '2:40.403' }, unit: 23, }, /* { 已移除 reference: 'we built the Tet our mission control', duration: { start: '2:40.000', end: '2:40.403' }, unit: 23, }, */ { reference: 'we built the Tet', duration: { start: '2:37.345', end: '2:38.500' }, unit: 23, }, /* { 已移除 reference: 'we built the Tet our mission control', duration: { start: '2:30.000', end: '2:40.403' }, unit: 23, } */ ];
修复方案
现有代码的核心问题是分组逻辑错误:仅用unit作为分组键,导致同一unit下不同reference的元素被互相覆盖,无法保留不同reference的条目;同时else分支直接覆盖旧元素的逻辑会丢失有效数据。
修改后的代码如下:
const array = [ { reference: 'Tet our mission not here', duration: { start: '2:33.213', end: '2:35.871' }, unit: 21, }, { reference: 'Tet our mission', duration: { start: '2:33.213', end: '2:35.871' }, unit: 22, }, { reference: 'we built the Tet our mission control', duration: { start: '2:10.000', end: '2:40.403' }, unit: 23, }, { reference: 'we built the Tet our mission control', duration: { start: '2:40.000', end: '2:40.403' }, unit: 23, }, { reference: 'we built the Tet', duration: { start: '2:37.345', end: '2:38.500' }, unit: 23, }, { reference: 'we built the Tet our mission control', duration: { start: '2:30.000', end: '2:40.403' }, unit: 23, } ]; console.log(getLongestByUnit(array)) function getLongestByUnit(array) { // 用`unit-reference`作为组合键,区分同一unit下不同reference的组 const groupMap = {}; array.forEach(el => { const key = `${el.unit}-${el.reference}`; const currentDuration = getSecondsDuration(el.duration.start, el.duration.end); const existing = groupMap[key]; if (!existing) { groupMap[key] = el; } else { const existingDuration = getSecondsDuration(existing.duration.start, existing.duration.end); // 仅当当前元素时长更长时才替换 if (currentDuration > existingDuration) { groupMap[key] = el; } } }); return Object.values(groupMap); } function getSecondsDuration(start, end) { const milisecondsDiff = (hrsToSecs(end) * 1000) - (hrsToSecs(start) * 1000); return milisecondsDiff / 1000; } function hrsToSecs(hrs) { var b = hrs.split(':'); return b.length > 2 ? b[0] * 3600 + b[1] * 60 + +b[2] : b[0] * 60 + +b[1]; }
关键改动点
- 分组键改为
${el.unit}-${el.reference},确保同一unit下不同reference的元素被分到独立的组中 - 移除错误的
else分支覆盖逻辑,仅在当前元素时长大于组内已有元素时才替换 - 提前计算当前元素和已有元素的时长,避免重复调用函数提升效率
内容的提问来源于stack exchange,提问作者user21189833
相关产品推荐
相关产品推荐

