如何用JavaScript合并无固定结构且含共同键值的关联数组?
解决方案:合并结构不固定的JavaScript对象数组
核心思路
要实现这类合并,关键是先定位两个数组中对象的共同键,再以这些共同键的组合值作为唯一标识,将两个数组中匹配的对象属性合并,最后整合所有不重复的记录。
步骤拆解与代码实现
1. 检测两个数组的共同键
遍历两个数组内所有对象的键,筛选出同时存在于两组对象中的键(注:键名默认区分大小写,比如location和Location会被视为不同键,需忽略大小写的话可额外处理)。
function findCommonKeys(arr1, arr2) { // 收集第一个数组所有对象的键 const keys1 = new Set(arr1.flatMap(obj => Object.keys(obj))); // 收集第二个数组所有对象的键 const keys2 = new Set(arr2.flatMap(obj => Object.keys(obj))); // 取交集得到共同键 return [...keys1].filter(key => keys2.has(key)); }
2. 合并对应键值与匹配记录
基于共同键生成唯一标识字符串,用Map存储第一个数组的记录,再遍历第二个数组,匹配对应记录并合并属性,最终将Map转为数组输出。
完整合并函数:
function mergeArrays(arr1, arr2) { // 第一步:找到共同键 const commonKeys = findCommonKeys(arr1, arr2); // 无共同键时直接合并两个数组 if (commonKeys.length === 0) { return [...arr1, ...arr2]; } // 第二步:用Map存储第一个数组的记录,键为共同键值的拼接字符串 const recordMap = new Map(); arr1.forEach(obj => { const keyStr = commonKeys.map(key => obj[key]).join('|'); recordMap.set(keyStr, { ...obj }); }); // 第三步:遍历第二个数组,匹配并合并记录 arr2.forEach(obj => { const keyStr = commonKeys.map(key => obj[key]).join('|'); if (recordMap.has(keyStr)) { // 合并属性,第二个数组的属性会覆盖第一个的(键重复时) recordMap.set(keyStr, { ...recordMap.get(keyStr), ...obj }); } else { // 无匹配记录则直接加入Map recordMap.set(keyStr, { ...obj }); } }); // 将Map的值转为数组返回 return [...recordMap.values()]; }
3. 测试示例
示例1:基于name字段合并
const arrA = [ { name: 'Stefano', age: 46 }, { name: 'Name2', age: 48 } ]; const arrB = [ { name: 'Stefano', location: 'Italy' }, { name: 'Name3', Location: 'Elsewhere' } ]; console.log(mergeArrays(arrA, arrB)); // 输出: // [ // { name: 'Stefano', age: 46, location: 'Italy' }, // { name: 'Name2', age: 48 }, // { name: 'Name3', Location: 'Elsewhere' } // ]
示例2:基于x、y字段合并
const arrC = [ { x:1, y:2, type:'a', category:8 }, { x:1, y:3, type:'a', category:9 } ]; const arrD = [ { x:1, y:2, bin:23, site:34 }, { x:1, y:3, bin:56, site:78 } ]; console.log(mergeArrays(arrC, arrD)); // 输出: // [ // { x:1, y:2, type:'a', category:8, bin:23, site:34 }, // { x:1, y:3, type:'a', category:9, bin:56, site:78 } // ]
额外说明
- 键名大小写处理:若需要忽略大小写,可在检测共同键和生成标识时统一转为小写/大写,修改
findCommonKeys及合并函数中的键处理逻辑即可。 - 属性覆盖规则:若要保留第一个数组的重复键属性,可调整扩展运算符顺序为
{ ...obj, ...recordMap.get(keyStr) }。 - 空数组兼容:函数已处理其中一个或两个数组为空的情况,返回合理结果。
内容的提问来源于stack exchange,提问作者Stefano Radaelli
相关产品推荐
相关产品推荐

