
本文介绍如何使用 javascript 的 `reduce` 方法,按指定属性(如 category)对对象数组进行分组,并将同组对象的其他属性合并到一个对象中,适用于处理分类统计、数据聚合等场景。
在实际开发中,我们常需将扁平的对象数组按某个分类字段(如 category)聚合成结构更紧凑的分组数据。例如,原始数据中每个对象代表一项活动及其价格,但类别重复出现;目标是将同一类别的所有子项(如 'Hang with Friends'、Chill)合并到一个对象中,保留 category 字段并动态添加其余键值对。
✅ 正确实现方式(推荐)
使用 Array.prototype.reduce() 配合一个临时对象作为累加器(acc),以 category 值为键存储分组对象,并用 Object.assign() 合并当前项:
const data = [
{ category: 'Entertainment', 'Hang with Friends': 100 },
{ category: 'Entertainment', Chill: 30 },
{ category: 'Health', Yoga: 40 },
{ category: 'Health', Birthday: 200 }
];
const grouped = Object.values(
data.reduce((acc, curr) => {
// 若 acc 中尚无该 category 对应的对象,则初始化为空对象
const target = (acc[curr.category] ??= {});
// 将 curr 的所有自有属性合并到 target 中(包括 category)
Object.assign(target, curr);
return acc;
}, {})
);
console.log(grouped);
// 输出:
// [
// { category: 'Entertainment', 'Hang with Friends': 100, Chill: 30 },
// { category: 'Health', Yoga: 40, Birthday: 200 }
// ]? 关键点解析: acc[curr.category] ??= {} 是空值合并赋值,确保每个 category 对应唯一对象引用; Object.assign(target, curr) 安全覆盖或新增属性(若存在同名 key,后者值生效); 最终用 Object.values() 提取所有分组对象,丢弃中间的键名(即 category 字符串)。
? 适配结构化数据格式(推荐数据建模方式)
你后续提供的标准化格式更清晰、更易维护:
const structuredData = [
{ category: 'Entertainment', subCategory: 'Hang with Friends', price: 100 },
{ category: 'Entertainment', subCategory: 'Chill', price: 30 },
{ category: 'Health', subCategory: 'Yoga', price: 40 },
{ category: 'Health', subCategory: 'Birthday', price: 200 }
];此时建议显式构造目标结构,避免直接合并 curr(防止 category 和 subCategory 冲突):
const groupedStructured = Object.values(
structuredData.reduce((acc, { category, subCategory, price }) => {
const group = (acc[category] ??= { category });
group[subCategory] = price; // 动态添加子类目与价格映射
return acc;
}, {})
);
console.log(groupedStructured);
// 输出:
// [
// { category: 'Entertainment', 'Hang with Friends': 100, Chill: 30 },
// { category: 'Health', Yoga: 40, Birthday: 200 }
// ]⚠️ 注意事项与最佳实践
- 不要用 category 字符串直接索引数组:字符串不能作为数组下标参与数值运算,必须使用对象({})或 Map 作哈希表;
- 避免副作用与可变状态:Object.assign() 修改的是已有对象,确保 target 是新引用或受控对象;
-
TypeScript 用户注意类型安全:
const grouped = Object.values( data.reduce
>>((acc, curr) => { const target = (acc[curr.category] ??= {}); Object.assign(target, curr); return acc; }, {}) ); - 性能考量:对于超大数据集(>10k 条),可考虑使用 Map 替代普通对象以规避原型链干扰,但日常场景 Object 已足够高效。
通过合理运用 reduce + 对象哈希 + Object.values(),你可以简洁、健壮地完成基于任意字符串字段的数组分组合并任务。










