javascript中用reduce实现数组去重的核心是累加器充当已见元素集合,通过set或map高效判重,支持基本类型和对象数组按字段去重,兼顾逻辑控制与性能优化。

JavaScript 中用 reduce 实现数组去重,核心在于利用累加器(accumulator)充当“已见元素集合”,逐个判断当前元素是否已存在,只保留首次出现的值。它比 filter + indexOf 更可控,也比 Set 多一层逻辑干预空间。
基础写法:配合对象或 Map 做存在性检查
由于数组元素可能是引用类型或需要严格比较,直接用对象键(字符串化)有局限;更稳妥的是用 Map 或 Set 配合 reduce:
- 用
Set记录已出现的值,适合基本类型(数字、字符串、布尔值) - 用
Map可支持对象/函数等复杂类型(需自定义 key 生成逻辑) - 累加器初始化为一个空数组,每次只在未见过时 push 当前元素
示例(基本类型去重):
const arr = [1, 2, 2, 3, 4, 4, 5];
const unique = arr.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
// → [1, 2, 3, 4, 5]
⚠️ 注意:includes 在大数组中性能较差。更优解是边遍历边维护一个 Set 作哈希查表:
const arr = [1, 2, 2, 3, 4, 4, 5];
const unique = arr.reduce(
(acc, cur) => {
if (!acc.seen.has(cur)) {
acc.seen.add(cur);
acc.result.push(cur);
}
return acc;
},
{ seen: new Set(), result: [] }
).result;
一行式简洁写法(适合简单场景)
如果只处理字符串/数字,且不追求极致性能,可结合扩展运算符和 Set:
const unique = [...new Set(arr)];
但这不算 reduce 实现。若坚持用 reduce 写成一行,可这样(牺牲可读性换简洁):
const unique = arr.reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], []);
✅ 优点:语义清晰、纯函数风格;❌ 缺点:每次展开数组有性能开销,不适合大数据量。
处理对象数组去重(按指定字段)
这是 reduce 真正体现“巧妙”的地方——可以灵活定义唯一性规则:
- 用
Map存储已出现的id或name值作为 key - 累加器仍是数组,但判重逻辑由你控制
示例(按 id 去重):
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice2' },
{ id: 3, name: 'Charlie' }
];
const uniqueUsers = users.reduce((acc, cur) => {
if (!acc.map.has(cur.id)) {
acc.map.set(cur.id, true);
acc.result.push(cur);
}
return acc;
}, { map: new Map(), result: [] }).result;
// → [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }]
小结:reduce 去重的关键设计点
累加器不是只能是数组——它可以是任意结构(对象、Map、Set、甚至布尔值),关键是承载“状态”;判重时机在回调内部,你可以插入日志、合并逻辑、跳过条件项;它天然支持链式数据流处理,比如去重 + 转换 + 过滤可一气呵成。
不复杂但容易忽略:别为了用 reduce 而用,小数组用 [...new Set()] 更直白;真要发挥 reduce 优势,就用在需要中间状态或复合逻辑的去重场景里。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











