
本文介绍如何在 JavaScript 中基于对象属性(如 name)将数组拆分为两个独立数组:一个包含所有重复出现的元素,另一个仅含首次出现且无重复的元素,适用于数据清洗与校验场景。
本文介绍如何在 javascript 中基于对象属性(如 `name`)将数组拆分为两个独立数组:一个包含所有重复出现的元素,另一个仅含首次出现且无重复的元素,适用于数据清洗与校验场景。
在实际前端开发或数据处理中,常需对用户导入的结构化数据(如客户列表)进行去重预检——但不同于简单保留首个副本,业务逻辑往往要求显式分离重复项与唯一项:前者交由用户人工核对修正,后者直接进入后续流程。本方案提供一种时间复杂度为 O(n)、语义清晰且易于维护的实现方式。
核心思路是利用 Map 按关键属性(如 name)聚合同名对象,再遍历分组结果,将长度大于 1 的组展开至重复数组,长度为 1 的组归入唯一数组:
const customers = [
{ id: 1, name: "John", address: "123 street" },
{ id: 2, name: "Alex", address: "456 street" },
{ id: 3, name: "John", address: "674 street" },
{ id: 4, name: "Stacy", address: "534 street" },
{ id: 5, name: "Blair", address: "634 street" }
];
// 步骤 1:按 name 分组,值为同名对象数组
const nameGroups = new Map();
customers.forEach(customer => {
const list = nameGroups.get(customer.name) || [];
list.push(customer);
nameGroups.set(customer.name, list);
});
// 步骤 2:分离重复项(≥2 个同名)与唯一项(仅 1 个)
const duplicates = [];
const uniques = [];
nameGroups.forEach((group, name) => {
if (group.length > 1) {
duplicates.push(...group);
} else {
uniques.push(...group);
}
});
console.log("重复项(需人工校验):", duplicates);
// → [{ id: 1, name: "John", ... }, { id: 3, name: "John", ... }]
console.log("唯一项(可直接处理):", uniques);
// → [{ id: 2, name: "Alex", ... }, { id: 4, name: "Stacy", ... }, { id: 5, name: "Blair", ... }]✅ 优势说明:
- 稳定性:严格保留原始顺序(因 forEach 遍历 Map 保持插入序,且 push(...group) 不打乱组内顺序);
- 可扩展性:只需修改 customer.name 为任意属性(如 customer.email 或 customer.phone),即可适配不同去重维度;
- 健壮性:自动处理空值或 undefined 属性(建议前置校验,见下方注意事项)。
⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 若 name 可能为 null/undefined,需先做规范化处理(例如 String(customer.name || '')),避免 Map 键冲突;
- 对于大小写敏感场景(如 "john" 和 "John" 视为不同),可统一转小写后再分组:customer.name?.toLowerCase();
- 如需支持多字段联合去重(如 name + email),可构造复合键:const key =${customer.name}|${customer.email}``。
该方法规避了嵌套循环的 O(n²) 开销,也优于多次 filter() + findIndex() 的低效组合,是兼顾性能、可读性与工程实践的推荐解法。










