
本文介绍如何将包含重复 vendorid 的对象数组按 id 合并,自动补全缺失字段(如 jan/feb/mar)并取非空值优先,最终生成结构统一、无重复 id 的聚合数组。
在实际数据处理中,我们常遇到原始数据分散在多个对象中、同一供应商(VendorID)的月份数据分条记录的情况。目标是将这些“碎片化”的记录按 VendorID 归并为单条完整记录,并对各月字段(如 "Jan"、"Feb"、"Mar")进行智能合并——优先保留非空/非零值,缺失字段则补默认值(如 "0"),确保最终结果结构规整、可直接用于表格渲染或后续计算。
以下是一个简洁、高效且易于扩展的纯 JavaScript 解决方案(无需 jQuery):
const testarray = [
{ "VendorID": "001", "Jan": "130", "Feb": "500" },
{ "VendorID": "001", "Jan": "0", "Feb": "0", "Mar": "1000" },
{ "VendorID": "002", "Mar": "20" }
];
// 步骤 1:按 VendorID 分组聚合(使用 reduce + Object.assign)
const grouped = testarray.reduce((acc, curr) => {
const existing = acc[curr.VendorID] || {};
// 合并当前项:后出现的属性值会覆盖前面的(但仅当其有定义时)
acc[curr.VendorID] = { ...existing, ...curr };
return acc;
}, {});
// 步骤 2:转换为数组,并标准化字段(确保所有月份键存在)
const finalarray = Object.values(grouped).map(item => ({
VendorID: item.VendorID,
Jan: item.Jan ?? "0",
Feb: item.Feb ?? "0",
Mar: item.Mar ?? "0"
}));
console.log(finalarray);
// 输出:
// [
// { VendorID: "001", Jan: "130", Feb: "500", Mar: "1000" },
// { VendorID: "002", Jan: "0", Feb: "0", Mar: "20" }
// ]✅ 关键优势说明:
- 使用 reduce 构建以 VendorID 为键的对象映射,天然去重且支持增量合并;
- 展开运算符 {...existing, ...curr} 实现浅层属性覆盖,后读入的数据中定义的字段会保留(例如 "001" 第二条的 "Mar" 覆盖第一条的缺失);
- ??(空值合并运算符)安全地提供默认值,比 || 更严谨(避免 "0" 被误判为 falsy);
- 完全不依赖 jQuery,兼容现代浏览器及 Node.js 环境。
⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 若需数值累加(如 "Jan" 字段应求和而非覆盖),请改用 parseInt(item.Jan) || 0 并在 reduce 中手动累加;
- 字段名(如 "Jan"/"Feb")若动态变化,建议预先提取所有可能键名:const allKeys = [...new Set(testarray.flatMap(o => Object.keys(o)))].filter(k => k !== 'VendorID');
- 原始代码中误用了 $.when($.each(...)) —— $.each 不返回 Promise,该写法逻辑无效,应避免混用 jQuery 异步工具与同步遍历。
通过此方法,你不仅能精准达成示例中的输出效果,还能灵活适配更多维度(如增加 "Apr"、"Q1" 等字段)与业务规则(如取最大值、平均值或首条非空值),真正实现健壮、可维护的数据聚合逻辑。










