用 reduce 实现数组分组统计的核心是初始化空对象,遍历中按字段动态更新属性:计数需 acc[key] = (acc[key] || 0) + 1,收集需 acc[key] = acc[key] || []; acc[key].push(item),多维度统计可设嵌套对象并分别更新。

用 reduce 实现数组分组统计,核心是把空对象作为初始值,遍历中按条件更新对象属性(如计数、求和、收集),最后返回该对象。
按某个字段分组并计数
适合统计每类出现次数,比如商品类别数量、用户状态分布等。
- 初始化一个空对象
{}作为累加器 - 每次遍历时,取出当前项的分组依据(如
item.type) - 若该 key 尚未存在,设为 0;然后自增 1
const list = [
{ name: '苹果', type: '水果' },
{ name: '香蕉', type: '水果' },
{ name: '胡萝卜', type: '蔬菜' }
];
const countByType = list.reduce((acc, item) => {
const key = item.type;
acc[key] = (acc[key] || 0) + 1;
return acc;
}, {});
// 结果:{ 水果: 2, 蔬菜: 1 }
按字段分组并收集原始项
适合归类后保留明细,比如按部门聚合员工列表、按日期归档日志。
一款AI音频处理工具,主要用于通过向 `toingg/make_campaign` API 发送 POST 请求,提交用户提供的 JSON 数据,创建并启动 Toingg 语音呼叫活动,适用于 Codex 将活动简报……,适合需要提升相关任务效率的用户。
- 同样以空对象为初始值
- 用
acc[key] = acc[key] || []确保对应 key 是数组 - 用
.push(item)或展开语法添加元素
const users = [
{ name: '张三', dept: '前端' },
{ name: '李四', dept: '后端' },
{ name: '王五', dept: '前端' }
];
const grouped = users.reduce((acc, user) => {
const key = user.dept;
if (!acc[key]) acc[key] = [];
acc[key].push(user);
return acc;
}, {});
// 结果:{ 前端: [{name:'张三',dept:'前端'}, ...], 后端: [...] }
多条件分组或复合统计
可以组合多个字段做 key,或同时维护多个统计维度(如总数、平均值、最大值)。
- key 可拼接,如
`${item.type}-${item.status}` - acc 中每个分组值可设为对象,存多个指标:
{ count: 0, sum: 0, items: [] } - 遍历时分别更新对应字段
const products = [
{ name: 'iPhone', type: '手机', price: 5999 },
{ name: 'iPad', type: '平板', price: 3299 },
{ name: 'Mac', type: '电脑', price: 12999 }
];
const stats = products.reduce((acc, p) => {
const key = p.type;
if (!acc[key]) {
acc[key] = { count: 0, total: 0 };
}
acc[key].count += 1;
acc[key].total += p.price;
return acc;
}, {});
// 结果:{ 手机: {count:1,total:5999}, 平板:{count:1,total:3299}, ... }
注意边界与可读性
避免常见坑,让逻辑更健壮、易维护。
- 确保分组字段存在且类型一致(建议先用
??或默认值兜底) - 如果 key 是对象或数组,需序列化(如
JSON.stringify),但慎用——可能影响性能和语义 - 复杂逻辑可提前抽成函数,如
getGroupKey(item),提升reduce内部的可读性 - 不推荐在
reduce中做副作用(如修改原数组、发请求),保持纯函数特性










