如何按Id键合并对象数组?已尝试方案未达预期求解决
合并对象数组的实现方案
需求规则
- 保留仅在单个数组中存在的
Id对应的对象 - 合并两个数组中
Id相同的对象,相同属性以第二个数组的值为准 - 原数组对象保持不变,所有对象均包含
Id属性
示例
const array1 = [ { Id: 'a1' }, { Id: 'a2', Name: 'Record 2', Cost: 4 } ]; const array2 = [ { Id: 'a2', Cost: 6 }, { Id: 'a3' } ]; // 预期结果 [ { Id: 'a1' }, { Id: 'a2', Name: 'Record 2', Cost: 6 }, { Id: 'a3' } ]
现有代码问题分析
代码1问题
function mergeArrays(array1, array2) { let array3 = array1.map((item, i) => Object.assign({}, item, array2[i])); return array3 }
这段代码通过索引位置合并元素,而非按Id匹配,导致只会合并两个数组对应索引的元素,既丢失了array2中独有的a3,也没正确处理Id匹配逻辑。
代码2问题
function mergeArrays(array1, array2) { const result = array2.map(item => { const searchedItem = array1.find(fItem => fItem['id'] === item['id'] ); if(searchedItem && Object.keys(searchedItem).length > 0 ){ item['id'] = searchedItem['id'] }else{ item['id'] = 'null' } return item; }); return result }
- 仅处理了
array2的元素,完全忽略array1中独有的a1; - 大小写错误:需求中是
Id属性,代码里写成了小写id,导致无法正确匹配; - 直接修改了
array2的原对象,违反了原数组对象保持不变的规则。
正确实现方案
核心思路是用Map存储所有Id对应的对象副本,先存入array1的内容,再用array2的内容覆盖或新增,最后导出结果数组:
function mergeArrays(array1, array2) { // 创建Map存储按Id分组的对象副本 const mergedMap = new Map(); // 先处理array1,存入所有对象的副本 array1.forEach(item => { mergedMap.set(item.Id, { ...item }); }); // 处理array2,合并或新增对象副本 array2.forEach(item => { const existingItem = mergedMap.get(item.Id); if (existingItem) { // 合并属性:用array2的属性覆盖array1的同名属性,生成新对象 mergedMap.set(item.Id, { ...existingItem, ...item }); } else { // 新增array2独有的对象副本 mergedMap.set(item.Id, { ...item }); } }); // 将Map的值转换为数组返回 return Array.from(mergedMap.values()); }
代码说明
- 使用
{ ...item }创建对象副本,确保原数组对象不会被修改; Map的set和get方法可以快速按Id查找匹配项,时间复杂度更优;- 合并时用
{ ...existingItem, ...item },自动让array2的属性覆盖array1的同名属性; - 最终通过
Array.from(mergedMap.values())得到包含所有结果的数组。
内容的提问来源于stack exchange,提问作者user18164791
相关产品推荐
相关产品推荐

