如何基于公共key合并两个含嵌套数组的对象数组?
基于公共ID合并对象数组并合并嵌套数组
需求说明
需要以id作为公共标识合并两个对象数组,同时合并对象中的嵌套数组accounts,保留所有在任意一个数组中存在的对象。
输入数组
第一个数组:
const arr1 = [ { id: 1, name: "sai", accounts: ["a"] }, { id: 2, name: "King", accounts:[] }, { id: 3, name: "Queen", accounts:["c"] }, { id: 4, name: "kai", accounts:["e"] }, ];
第二个数组:
const arr2 = [ { id: 1, age: 23, accounts: ["b"] }, { id: 2, age: 24, accounts:[] }, { id: 3, age: 25, accounts:["d"] } ];
期望输出
[ { id: 1, age: 23, name:"sai", accounts: ["a","b"] }, { id: 2, age: 24, name: "King", accounts:[] }, { id: 3, age: 25, name:"Queen", accounts:["c","d"] }, { id: 4, name: "kai", accounts:["e"] }, ]
解决方案
可以利用Map高效实现合并逻辑,具体代码如下:
const arr1 = [ { id: 1, name: "sai", accounts: ["a"] }, { id: 2, name: "King", accounts:[] }, { id: 3, name: "Queen", accounts:["c"] }, { id: 4, name: "kai", accounts:["e"] }, ]; const arr2 = [ { id: 1, age: 23, accounts: ["b"] }, { id: 2, age: 24, accounts:[] }, { id: 3, age: 25, accounts:["d"] } ]; const mergeArrays = (arrA, arrB) => { const mergedMap = new Map(); // 先存入第一个数组的对象,避免修改原数据 arrA.forEach(item => mergedMap.set(item.id, {...item})); // 遍历第二个数组,合并到已有对象或新增 arrB.forEach(item => { const existingItem = mergedMap.get(item.id); if (existingItem) { Object.keys(item).forEach(key => { if (Array.isArray(item[key])) { // 合并嵌套数组 existingItem[key] = [...existingItem[key], ...item[key]]; } else { // 添加原对象没有的普通属性 if (!(key in existingItem)) { existingItem[key] = item[key]; } } }); } else { mergedMap.set(item.id, {...item}); } }); return Array.from(mergedMap.values()); }; // 得到合并结果 const mergedResult = mergeArrays(arr1, arr2); console.log(mergedResult);
逻辑说明
- 用Map存储对象:通过
id作为键存储对象,保证查找和修改的效率为O(1) - 处理第一个数组:将每个对象浅拷贝后存入Map,避免修改原数组数据
- 合并第二个数组:
- 若当前对象的
id已存在于Map中,遍历其属性:数组类型属性直接拼接,普通属性仅在原对象无该属性时添加 - 若
id不存在,直接将当前对象存入Map
- 若当前对象的
- 转换为数组:将Map中的值转换为数组,得到最终合并结果
内容的提问来源于stack exchange,提问作者sevack
相关产品推荐
相关产品推荐

