
本文详解如何利用数组的 reduce() 高阶函数高效统计每个元素的出现频次,生成键值对形式的计数对象,并附带可运行示例、关键逻辑说明与常见注意事项。
本文详解如何利用数组的 `reduce()` 高阶函数高效统计每个元素的出现频次,生成键值对形式的计数对象,并附带可运行示例、关键逻辑说明与常见注意事项。
在 JavaScript 中,Array.prototype.reduce() 是一个功能强大且富有表现力的高阶函数,适用于将数组“折叠”为单一值(如数字、字符串或对象)。统计数组中各元素的出现次数,正是 reduce() 的典型应用场景之一——它天然契合“累积状态”的建模需求:以空对象作为初始累加器(acc),遍历每个当前元素(curr),动态更新其计数值。
以下是一个简洁、健壮的实现:
const array = [1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 1, 2, 3, 3, 3, 3, 3, 4, 98, -546, 4];
const countMap = array.reduce((acc, curr) => {
acc[curr] = (acc[curr] || 0) + 1;
return acc;
}, {});
console.log(countMap);
// 输出:
// {
// '1': 4, '2': 4, '3': 8, '4': 3, '5': 1,
// '6': 1, '7': 1, '98': 1, '-546': 1
// }✅ 核心逻辑解析:
- 初始值 {} 作为累加器 acc,用于存储各元素及其计数;
- 每次迭代中,acc[curr] || 0 确保首次遇到该元素时从 0 开始计数,避免 undefined + 1 导致 NaN;
- acc[curr] += 1(等价于 acc[curr] = (acc[curr] || 0) + 1)完成自增;
- 必须显式 return acc,否则下一轮迭代的 acc 将变为 undefined,导致报错。
? 进阶提示:
立即学习“Java免费学习笔记(深入)”;
- 若需统计严格相等(如区分 0 和 -0、null 和 undefined),上述方案已满足(因对象键会自动转为字符串,但 0 与 -0 在对象键中均转为 '0');如需更高精度,可改用 Map 代替普通对象:
const countMap = array.reduce((map, curr) => map.set(curr, (map.get(curr) || 0) + 1), new Map());
- 若只需统计某一个特定元素(如只查 3 出现几次),可简化为:
const countOfThree = array.reduce((sum, num) => num === 3 ? sum + 1 : sum, 0); // → 8
⚠️ 注意事项:
- 不要省略 reduce 的第二个参数(初始值),否则首次调用时 acc 会是数组第一个元素,逻辑将完全错误;
- 对象键始终为字符串类型(如 -546 变成 '-546'),若后续需数值运算,请注意类型转换;
- reduce 是纯函数式写法,不修改原数组,符合不可变数据原则,利于调试与测试。
掌握这一模式,不仅能解决计数问题,更能深化对函数式编程思维的理解——把“状态变化”封装进累加器,让代码更声明式、更可预测。










