JavaScript 基于指定键合并n个对象数组 补全缺失字段为0的实现
原实现的核心问题
- 仅以第一个入参数组的元素为遍历基准,完全遗漏了第二个数组中的独有日期条目,比如2017-01-19的记录根本不会被纳入结果
- 做匹配查找时,
Array.find找不到对应项会返回undefined,展开后不会自动给缺失的业务字段补0,甚至会出现字段缺失的情况 - 没有统一的字段初始化逻辑,最终输出的对象结构不统一,不符合业务要求
符合预期的双数组合并实现
可直接运行,输出结果完全匹配业务要求:
const arr1 = [ { old_clicks: 1, date: "2017-01-24" }, { old_clicks: 4, date: "2017-01-22" }, { old_clicks: 6, date: "2017-01-21" } ]; const arr2 = [ { total_clicks:120, date: "2017-01-21" }, { total_clicks: 100, date: "2017-01-19" } ]; const mergeByKey = (a1, a2, mergeKey) => { // 收集所有出现过的唯一合并键值,保持原插入顺序 const allUniqueKeys = new Set([ ...a1.map(item => item[mergeKey]), ...a2.map(item => item[mergeKey]) ]); // 收集所有业务字段,后续用来补默认值0 const allBizFields = Array.from(new Set([ ...a1.flatMap(item => Object.keys(item).filter(k => k !== mergeKey)), ...a2.flatMap(item => Object.keys(item).filter(k => k !== mergeKey)) ])); // 建立快速查找索引,避免反复遍历数组做匹配 const indexA = new Map(a1.map(item => [item[mergeKey], item])); const indexB = new Map(a2.map(item => [item[mergeKey], item])); return Array.from(allUniqueKeys).map(key => { // 初始化每条合并结果,所有业务字段默认填0 const mergedRow = Object.fromEntries(allBizFields.map(field => [field, 0])); mergedRow[mergeKey] = key; // 叠加两个数组中对应合并键的实际值 return { ...mergedRow, ...(indexA.get(key) || {}), ...(indexB.get(key) || {}) } }) } const result = mergeByKey(arr1, arr2, 'date');
运行上述代码的输出完全符合预期:
- 覆盖两个数组所有日期,无条目遗漏
- 同合并键的对象字段自动合并
- 单数组独有的日期,对应另一数组的业务字段自动补0
支持多数组通用合并的优化版本
如果后续需要合并超过2个数组,可以把函数调整为接收数组列表的形式,无需修改核心逻辑:
const mergeMultiArrays = (arrayList, mergeKey) => { const allUniqueKeys = new Set( arrayList.flatMap(arr => arr.map(item => item[mergeKey])) ); const allBizFields = Array.from(new Set( arrayList.flatMap(arr => arr.flatMap(item => Object.keys(item).filter(k => k !== mergeKey)) ) )); // 为每个待合并数组建立索引 const indexList = arrayList.map(arr => new Map(arr.map(item => [item[mergeKey], item]))); return Array.from(allUniqueKeys).map(uniqueKey => { const mergedRow = Object.fromEntries(allBizFields.map(field => [field, 0])); mergedRow[mergeKey] = uniqueKey; // 依次叠加每个数组的对应值 indexList.forEach(index => Object.assign(mergedRow, index.get(uniqueKey) || {})); return mergedRow; }) } // 使用时直接传入所有待合并数组、合并键即可 const result = mergeMultiArrays([arr1, arr2], 'date');
内容的提问来源于stack exchange,提问作者Aayush Bansal
相关产品推荐
相关产品推荐

