Node.js(ES6) 如何对对象数组去重并保留最新录入的条目
最优实现方案
最高效的实现方式是用ES6 Map做中间存储,整体时间复杂度为O(n),仅需遍历数组一次,不需要额外排序开销,完全匹配所有去重规则:
实现代码
function deduplicateContacts(contacts) { const contactMap = new Map() for (const item of contacts) { // 生成contact+value的组合唯一键 const uniqueKey = `${item.contact}:${item.value}` // 将mm-dd-yyyy格式的日期转为yyyyMMdd格式的数字,可直接比较大小 const [curMonth, curDay, curYear] = item.entered.split('-') const curDateWeight = Number(`${curYear}${curMonth}${curDay}`) if (!contactMap.has(uniqueKey)) { // 首次出现的组合直接存入Map contactMap.set(uniqueKey, { ...item, _dateWeight: curDateWeight }) continue } const existedItem = contactMap.get(uniqueKey) // 仅当当前条目日期更新时才替换已有条目 // 日期相同时不替换,自然保留索引更小的先出现条目,匹配规则3 if (curDateWeight > existedItem._dateWeight) { contactMap.set(uniqueKey, { ...item, _dateWeight: curDateWeight }) } } // 提取结果并移除临时添加的日期权重字段 return Array.from(contactMap.values(), ({ _dateWeight, ...rest }) => rest) } // 测试用例 const contacts = [ {contact: "mobileno", value: "123456789", entered: "03-02-2021"}, {contact: "email", value: "test1@test.com", entered: "03-02-2021"}, {contact: "mobileno", value: "123456789", entered: "03-03-2021"}, {contact: "mobileno", value: "558843721", entered: "03-04-2021"}, {contact: "email", value: "test2@test.com", entered: "03-05-2021"}, {contact: "email", value: "test2@test.com", entered: "03-06-2021"}, ] console.log(deduplicateContacts(contacts))
逻辑说明
- 唯一性判定:用
contact和value拼接成唯一键,直接用Map的键唯一性做校验,读写都是O(1)操作 - 日期对比:直接将日期转为yyyyMMdd格式的数字做大小对比,比转Date对象性能更高
- 索引优先级:因为是正序遍历原始数组,相同日期的重复条目不会替换先存入的条目,自然保留索引更小的条目
- 如果需要和示例输出一致按录入日期升序排列,可在返回结果前加排序逻辑:
return Array.from(contactMap.values(), ({ _dateWeight, ...rest }) => rest) .sort((a, b) => { const [m1, d1, y1] = a.entered.split('-') const [m2, d2, y2] = b.entered.split('-') return new Date(y1, m1 - 1, d1) - new Date(y2, m2 - 1, d2) })
内容的提问来源于stack exchange,提问作者Xmus Jackson Flaxon Waxon
相关产品推荐
相关产品推荐

