
本文介绍如何将包含重复 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 等框架的数据预处理流程。










