reduce 清理重复数据核心是用对象或 map 当缓存,遍历中只留首次/末次项或合并字段,适用于保留顺序、按 id/复合键去重及不可变更新场景。

用 reduce 清理状态中重复数据,核心是利用对象或 Map 作“去重缓存”,遍历过程中只保留首次出现的项。它不直接去重(如 Set 那样),而是通过逻辑控制累积结果,特别适合处理带结构、需保留原始顺序或需合并字段的场景。
按 ID 去重并保留最后/首个出现的项
常见于列表更新:后端多次推送部分数据,前端需合并去重。用 reduce 配合对象键唯一性,轻松实现:
const list = [
{ id: 1, name: "Alice", score: 85 },
{ id: 2, name: "Bob", score: 92 },
{ id: 1, name: "Alice", score: 88 }, // 重复 id,score 更新了
{ id: 3, name: "Charlie", score: 76 }
];
// 保留每个 id 最后一次出现的数据(覆盖式)
const uniqueByIdLast = list.reduce((acc, item) => {
acc[item.id] = item; // 直接赋值,后出现的覆盖前出现的
return acc;
}, {});
const resultLast = Object.values(uniqueByIdLast);
// → [{id:1,score:88}, {id:2,score:92}, {id:3,score:76}]
// 若想保留第一个出现的(不覆盖),加判断:
const uniqueByIdFirst = list.reduce((acc, item) => {
if (!acc[item.id]) acc[item.id] = item;
return acc;
}, {});
合并重复项的特定字段(如累加数量)
状态中可能有多个同 ID 商品项,需合并为一条并累加 count:
const cartItems = [
{ id: 101, name: "Book", count: 1 },
{ id: 102, name: "Pen", count: 2 },
{ id: 101, name: "Book", count: 3 } // 同商品再次加入
];
const mergedCart = Object.values(
cartItems.reduce((acc, item) => {
if (acc[item.id]) {
acc[item.id].count += item.count; // 合并数量
} else {
acc[item.id] = { ...item }; // 浅拷贝,避免引用污染
}
return acc;
}, {})
);
// → [{id:101,name:"Book",count:4}, {id:102,name:"Pen",count:2}]
按复合条件去重(如 name + category 联合唯一)
当单个字段不足以标识唯一性时,构造唯一 key:
const products = [
{ name: "iPhone", category: "phone", price: 999 },
{ name: "iPhone", category: "tablet", price: 399 }, // 同名不同类,应保留
{ name: "iPhone", category: "phone", price: 1099 } // 真正重复
];
const uniqueByComposite = Object.values(
products.reduce((acc, item) => {
const key = `${item.name}|${item.category}`;
if (!acc[key]) acc[key] = item;
return acc;
}, {})
);
// 正确保留两条 iPhone,过滤掉 price 更新的重复项
配合 Immutable 状态更新(React / Redux 场景)
在不可变更新中,避免直接修改原状态。用 reduce 构建全新数组或对象:
// 假设 state.items 是当前列表,action.payload 是新收到的一批数据
const newState = {
...state,
items: Object.values([
...state.items,
...action.payload
].reduce((acc, item) => {
acc[item.id] = acc[item.id]
? { ...acc[item.id], ...item } // 浅合并:新字段覆盖旧值
: { ...item };
return acc;
}, {}))
};
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











