
本文介绍一种简洁高效的方法:利用 javascript 对象(或 map)以“客户名-产品码”为唯一键,自动保留每个客户每种产品的首条记录,完美满足无重复客户全保留、有重复客户则按产品去重的复合筛选需求。
本文介绍一种简洁高效的方法:利用 javascript 对象(或 map)以“客户名-产品码”为唯一键,自动保留每个客户每种产品的首条记录,完美满足无重复客户全保留、有重复客户则按产品去重的复合筛选需求。
在处理嵌套二维数组(如导出报表、CRM 数据等)时,常需按多维度逻辑去重——并非简单去除完全重复项,而是实现「按客户分组 → 组内按产品去重 → 仅保留首次出现的产品记录」。上述需求看似复杂,但借助 JavaScript 的对象键唯一性特性,可一行逻辑优雅解决。
核心思路是:将 clientName + "-" + productCode 拼接为字符串键,作为哈希表(plain object 或 Map)的 key;遍历原始数组时,若该键尚未存在,则存入当前整行数据;若已存在,则跳过——天然保证每个客户+产品的组合仅保留第一条记录。
以下是完整可运行示例:
let testArray = [
["ASDF245", "Jeff Hill", "BOP"],
["ASCG285", "Jerry F Tate", "BOP"],
["ASDF240", "Jeff Hill", "WC"],
["ASDF291", "Jake Sab", "BOP"],
["ASDF301", "Mary Stein", "WC"],
["ASDF460", "Jeff Hill", "WC"],
["ASDF245", "Hello Dup", "BOP"],
["ASDF245", "Hello Dup", "BOP"],
["ASDF245", "Hello Dup", "WC"]
];
// ✅ 推荐方案:使用对象字面量 + 逻辑赋值(ES2021+)
const uniqueByClientAndProduct = {};
testArray.forEach(([id, name, product]) => {
const key = `${name}-${product}`;
// ||= 等价于:uniqueByClientAndProduct[key] = uniqueByClientAndProduct[key] || [id, name, product];
uniqueByClientAndProduct[key] ??= [id, name, product];
});
const result = Object.values(uniqueByClientAndProduct);
console.log(result);
// 输出:
// [
// ["ASDF245", "Jeff Hill", "BOP"],
// ["ASCG285", "Jerry F Tate", "BOP"],
// ["ASDF240", "Jeff Hill", "WC"],
// ["ASDF291", "Jake Sab", "BOP"],
// ["ASDF301", "Mary Stein", "WC"],
// ["ASDF245", "Hello Dup", "BOP"],
// ["ASDF245", "Hello Dup", "WC"]
// ]? 关键说明:
- 此方案自动兼容两类场景:
- 客户名唯一(如 "Jerry F Tate")→ 全部保留;
- 客户名重复(如 "Jeff Hill" 出现 3 次,对应 "BOP"/"WC"/"WC")→ 仅保留 "BOP" 和首个 "WC"(即 ["ASDF240", "Jeff Hill", "WC"]),忽略第二个 "WC" 行(["ASDF460", "Jeff Hill", "WC"]);
- 同理,"Hello Dup" 的重复 "BOP" 行被跳过,仅留首条。
- 使用 ??=(空值合并赋值)比 ||= 更安全:当某行 id 为 0、"" 或 false 等 falsy 值时,||= 会错误触发覆盖,而 ??= 仅在 undefined 或 null 时生效。
- 若需兼容旧版浏览器,可替换为:
if (!uniqueByClientAndProduct[key]) { uniqueByClientAndProduct[key] = [id, name, product]; }
✅ 进阶建议:
- 如需保持原始顺序(按首次出现顺序输出),Object.values() 在现代引擎中默认按插入顺序返回,可放心使用;
- 若数据量极大(>10 万行),建议改用 Map 替代 plain object,避免原型链干扰且性能更稳定:
const map = new Map(); testArray.forEach(([id, name, product]) => { const key = `${name}-${product}`; if (!map.has(key)) map.set(key, [id, name, product]); }); const result = [...map.values()];
该方法摒弃了嵌套循环、多重 filter 和状态管理的复杂性,以声明式思维直击本质——用哈希唯一性解决多条件去重,代码简洁、逻辑清晰、性能优异,是处理此类业务数据的理想实践。

















