
本文介绍如何将包含重复 vendorid 的对象数组按 id 合并,自动聚合各月字段(如 jan、feb、mar),缺失字段补 0,最终生成结构统一、无重复 id 的规范化数组。
在实际数据处理中,我们常遇到原始数据以“稀疏记录”形式存在:同一供应商(VendorID)的销售或费用信息分散在多条记录中,每条仅填充部分月份字段。目标是将其归并为一条完整记录,实现字段优先级覆盖(后出现的非空值覆盖前值)并补齐缺失字段为默认值(如 0)。以下是一种简洁、可读性强且不依赖外部库的原生 JavaScript 实现方案。
核心思路
- 遍历原始数组,对每个对象按 VendorID 进行分组归并;
- 使用 Array.prototype.find() 定位已存在的同 ID 记录;
- 利用对象展开语法 {...existing, ...new} 实现字段合并——注意:后出现的属性会覆盖先出现的(即“后写入优先”),这恰好满足“用新值补充旧记录”的需求;
- 最后统一标准化字段结构,确保所有输出对象都包含 Jan、Feb、Mar 等键,并将 undefined 或空字符串转换为数值 0(可根据业务需要改为 "" 或 "N/A")。
完整实现代码
const testarray = [
{ "VendorID": "001", "Jan": "130", "Feb": "500" },
{ "VendorID": "001", "Jan": "0", "Feb": "0", "Mar": "1000" },
{ "VendorID": "002", "Mar": "20" }
];
const result = [];
testarray.forEach(entry => {
const existing = result.find(item => item.VendorID === entry.VendorID);
if (existing) {
// 移除原记录,合并后重新加入(保证顺序与首次出现一致)
const index = result.indexOf(existing);
result.splice(index, 1, { ...existing, ...entry });
} else {
result.push({ ...entry });
}
});
// 标准化字段:强制包含 Jan/Feb/Mar,空值转为 0(数值型更利于后续计算)
const finalarray = result.map(item => ({
VendorID: item.VendorID,
Jan: Number(item.Jan) || 0,
Feb: Number(item.Feb) || 0,
Mar: Number(item.Mar) || 0
}));
console.log(finalarray);
// 输出:
// [
// { VendorID: "001", Jan: 0, Feb: 0, Mar: 1000 }, ← 注意:此处 "Jan": "0" 覆盖了 "130"
// { VendorID: "002", Jan: 0, Feb: 0, Mar: 20 }
// ]⚠️ 重要说明与注意事项:
无论从何种情形出发,在目前校长负责制的制度安排下,中小学校长作为学校的领导者、管理者和教育者,其管理水平对于学校发展的重要性都是不言而喻的。从这个角度看,建立科学的校长绩效评价体系以及拥有相对应的评估手段和工具,有利于教育行政机关针对校长的管理实践全过程及其结果进行测定与衡量,做出价值判断和评估,从而有利于强化学校教学管理,提升教学质量,并衍生带来校长转变管理观念,提升自身综合管理素质。
- 上述实现遵循“后写入优先”原则。例如 VendorID: "001" 的第二条记录中 "Jan": "0" 会覆盖第一条的 "130"。若需“保留首次非空值”,应改用条件赋值逻辑(如 Jan: item.Jan != null ? item.Jan : existing?.Jan)。
- Number(...) 转换可防止字符串 "0" 被误判为 falsy;若需保留字符串格式,可改用 item.Jan ?? "0"。
- 若月份字段动态不确定(如新增 Apr、May),建议先扫描全量 key 集合,再做统一初始化,避免硬编码。
- 性能提示:对于超大数据集(>10,000 条),find() + splice() 的 O(n²) 复杂度可能成为瓶颈,此时推荐改用 Map 做 O(1) ID 索引:
const map = new Map();
testarray.forEach(entry => {
const id = entry.VendorID;
const existing = map.get(id) || {};
map.set(id, { ...existing, ...entry });
});
const finalarray = Array.from(map.values()).map(item => ({
VendorID: item.VendorID,
Jan: Number(item.Jan) || 0,
Feb: Number(item.Feb) || 0,
Mar: Number(item.Mar) || 0
}));该方案兼顾可读性、健壮性与扩展性,适用于报表汇总、前端数据预处理等典型场景。









