
本文介绍如何用一次 reduce 操作高效统计方向数组中各元素出现次数,并映射为语义化键名的对象,避免重复 filter 和多次 reduce,提升代码简洁性与性能。
本文介绍如何用一次 reduce 操作高效统计方向数组中各元素出现次数,并映射为语义化键名的对象,避免重复 filter 和多次 reduce,提升代码简洁性与性能。
在处理方向路径(如 'n'、's')的频次统计时,原代码通过两次 filter + reduce 分别计算 'n' 和 's' 的数量,不仅冗余,还违背了函数式编程“单遍处理”的原则。更优雅的方式是仅遍历一次数组,动态累积每种方向的计数。
核心思路是:将 reduce 的累加器设为一个空对象 {},每次迭代根据当前方向(如 'n')作为键,更新对应值(初始为 0,然后 +1):
const walk = ['n', 's', 'n', 's', 'n', 's', 'n', 's', 'n', 's'];
const result = walk.reduce((acc, direction) => {
acc[direction] = (acc[direction] || 0) + 1;
return acc;
}, {});
console.log(result); // { n: 5, s: 5 }✅ 优势明显:
- 时间复杂度 O(n):仅一次遍历;
- 空间高效:无需中间数组(filter 会创建新数组);
- 可扩展性强:自动支持新增方向(如 'e'、'w'),无需修改逻辑。
⚠️ 注意事项:
- 若需将简写键('n')映射为语义化键('north'),可在 reduce 内部做映射:
const dirMap = { n: 'north', s: 'south', e: 'east', w: 'west' }; const result = walk.reduce((acc, d) => { const key = dirMap[d] || d; // 默认保留原值 acc[key] = (acc[key] || 0) + 1; return acc; }, {}); // → { north: 5, south: 5 } - 避免在 reduce 中直接修改外部对象(如题中 object),应始终返回新状态,确保纯函数特性。
总结:reduce 的本质是“累积状态”,而非仅用于数值计算。将其累加器设为对象,配合逻辑或运算符 || 提供默认值,即可优雅实现分组计数——这是函数式数据聚合的经典范式。


















