
本文介绍如何将包含重复 vendorid 的对象数组按 id 合并,自动补全缺失月份字段(如 jan/feb/mar)并保留非零优先或覆盖式值,最终生成结构统一、无重复 id 的聚合结果。
在实际数据处理中,我们常遇到原始数据分散在多个对象中、同一 VendorID 出现在多条记录里的场景。例如销售数据按月分片上报,导致 “001” 供应商的 Jan 和 Feb 出现在第一条,而 Mar 出现在第二条。此时需将同 ID 的所有字段“合并到一行”,并确保最终结果中每个 VendorID 对应唯一对象,且所有关键字段(如 Jan、Feb、Mar)均存在——缺失则默认为 “0” 或 0。
下面是一个简洁、可读性强且不依赖外部库的核心实现方案(使用原生 javaScript):
const testarray = [ { "VendorID": "001", "Jan": "130", "Feb": "500" }, { "VendorID": "001", "Jan": "0", "Feb": "0", "Mar": "1000" }, { "VendorID": "002", "Mar": "20" } ]; // 步骤 1:按 VendorID 分组聚合 const grouped = new Map(); testarray.forEach(item => { const id = item.VendorID; if (!grouped.has(id)) { grouped.set(id, {}); } // 浅合并:后出现的属性值覆盖前序(适用于“非空优先”逻辑) Object.assign(grouped.get(id), item); }); // 步骤 2:标准化字段,补全缺失月份(设为 "0" 字符串以保持类型一致) const allMonths = ["Jan", "Feb", "Mar"]; const finalarray = Array.from(grouped.values()).map(obj => { const normalized = { VendorID: obj.VendorID }; allMonths.forEach(month => { normalized[month] = obj[month] !== undefined ? obj[month] : "0"; }); return normalized; }); console.log(finalarray); // 输出: // [ // { "VendorID": "001", "Jan": "0", "Feb": "0", "Mar": "1000" }, // { "VendorID": "002", "Jan": "0", "Feb": "0", "Mar": "20" } // ]
⚠️ 注意事项:
- 覆盖逻辑说明:上述 Object.assign() 采用“后写入优先”,即若 VendorID=”001″ 的两条记录都含 Jan,则第二条的 “0” 会覆盖第一条的 “130”。若需“非空优先”(保留 “130”),可改用更智能合并函数:
Object.keys(item).forEach(key => { if (key !== 'VendorID' && (obj[key] === undefined || obj[key] === "0")) { obj[key] = item[key]; } }); - 类型一致性:示例中保留字符串型数值(如 “130”)。如需统一转为数字,可在归一化阶段使用 number(obj[month]) || 0。
- 可扩展性:allMonths 数组可动态提取自所有对象的键(排除 VendorID),实现全自动字段发现。
该方法避免了低效的嵌套循环与频繁 Filter/find,时间复杂度为 O(n),清晰表达“分组 → 合并 → 补全”三步逻辑,适用于中等规模数据聚合,亦可轻松适配 vue/react 等框架的数据预处理流程。