如何使用Array.reduce()对数组对象去重合并后返回新数组
使用Array.reduce()合并重复数组项实现方案
实现逻辑
重复判定规则:color和type字段同时相等的条目视为重复项,重复项保留一条,count字段做累加求和。
遍历过程中直接以结果数组作为累加容器,每轮遍历检查容器内是否已存在同标识条目:存在则累加count,不存在则插入新条目。
可直接运行的完整代码
const product = [ { color: 'orange', type: 'hat', count: 1 }, { color: 'orange', type: 'hat', count: 1 }, { color: 'orange', type: 'shoes', count: 1 }, { color: 'blue', type: 'food', count: 1 }, ]; const result = product.reduce((acc, curr) => { // 匹配已存在的同色同类型条目 const target = acc.find(item => item.color === curr.color && item.type === curr.type); if (target) { // 重复项累加count target.count += curr.count; } else { // 新条目浅拷贝后推入结果,避免修改原数组 acc.push({ ...curr }); } return acc; }, []); // 初始值必须传空数组,否则首轮遍历acc为数组第一个元素会导致逻辑异常
运行后result的输出完全符合预期:
[ { color: 'orange', type: 'hat', count: 2 }, { color: 'orange', type: 'shoes', count: 1 }, { color: 'blue', type: 'food', count: 1 }, ]
大数据量优化版本
如果待处理的数组长度很大,上面用find遍历查找的方式时间复杂度是O(n²),性能较差,可以用Map做索引把时间复杂度降到O(n),代码如下:
const result = product.reduce((acc, curr) => { const key = `${curr.color}_${curr.type}`; const exist = acc.map.get(key); if (exist) { exist.count += curr.count; } else { const newItem = { ...curr }; acc.map.set(key, newItem); acc.list.push(newItem); } return acc; }, { list: [], map: new Map() }).list;
注意点
- 不要省略reduce的第二个初始值参数,不传的话默认以数组第一个元素作为初始acc,类型为对象不是数组,调用push/find方法会直接报错
- 插入新条目时做浅拷贝,避免后续修改count值时污染原始数组里的对象
内容的提问来源于stack exchange,提问作者cindy
相关产品推荐
相关产品推荐

