如何合并两个对象数组并对相同id的qty字段值求和?
合并对象数组并累加相同id的qty值
问题描述
我有以下两个对象数组:
const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}]; const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}];
希望合并这两个数组,同时将id相同的对象的qty值相加,预期输出:
[{"id":"pear","qty":7},{"id":"apple","qty":2},{"id":"lemon","qty":1}];
我尝试了以下代码,但它只保留了部分匹配对象,结果不符合预期:
const newArray = arr1.map((obj) => { const secondArrayObj = arr2.find((obj2) => obj2.id === obj.id); if (secondArrayObj) { return {...secondArrayObj, ...obj} } return null; }).filter((obj) => obj != null); console.log(newArray);
请问最优的实现方法是什么?
问题分析
当前代码存在两个核心问题:
- 仅遍历
arr1,arr2中独有的元素(比如lemon)被完全忽略; - 合并对象时用
arr1的qty覆盖了arr2的qty,并未实现累加,甚至会得到错误的数值。
最优实现方法
推荐使用Map来处理,时间复杂度为O(n+m)(n和m分别是两个数组的长度),效率远高于嵌套查找的O(n*m):
const mergeArrays = (arr1, arr2) => { const qtyMap = new Map(); // 处理第一个数组,初始化或累加qty arr1.forEach(item => { qtyMap.set(item.id, (qtyMap.get(item.id) || 0) + item.qty); }); // 处理第二个数组,继续累加或新增 arr2.forEach(item => { qtyMap.set(item.id, (qtyMap.get(item.id) || 0) + item.qty); }); // 将Map转换为目标数组格式 return Array.from(qtyMap, ([id, qty]) => ({ id, qty })); }; const arr1 = [{"id":"pear","qty":2},{"id":"apple","qty":2}]; const arr2 = [{"id":"pear","qty":5},{"id":"lemon","qty":1}]; console.log(mergeArrays(arr1, arr2)); // 输出:[{"id":"pear","qty":7},{"id":"apple","qty":2},{"id":"lemon","qty":1}]
代码说明
- Map的作用:以
id为键存储对应qty的累加值,确保每个id只保留一条记录; - 遍历处理:分别遍历两个数组,对每个元素,若
id已存在则累加qty,不存在则初始化数值; - 格式转换:用
Array.from将Map的键值对转换为要求的对象数组格式。
如果想要更紧凑的写法,可以合并两次遍历:
const mergeArrays = (arr1, arr2) => { const qtyMap = new Map(); // 合并两个数组后一次性遍历处理 [...arr1, ...arr2].forEach(item => { qtyMap.set(item.id, (qtyMap.get(item.id) || 0) + item.qty); }); return Array.from(qtyMap, ([id, qty]) => ({ id, qty })); };
这种写法逻辑更简洁,最终效果完全一致。
内容的提问来源于stack exchange,提问作者Cain Nuke
相关产品推荐
相关产品推荐

