如何仅用reduce统计数组中字符串出现次数(部分需先拆分)
单次reduce统计数组元素出现次数
需求与现有解法
给定包含多元素拼接字符串的数组:
const myArr = ["a, b, c", "a", "b", "a, b", "b", "a", "a", "a, b, c, d"]
需要统计其中a、b、c、d各自的出现次数。
现有通过map()+split()+flat()+reduce()的实现方式可以得到正确结果:
const res = myArr.map((x) => x.split(", ")).flat().reduce((acc, x) => { return acc[x] ? ++acc[x] : (acc[x] = 1), acc; }, {}); console.log(res) // { a: 6, b: 5, c: 2, d: 1 }
但希望仅通过一次reduce()调用完成所有统计操作,避免创建中间数组。
用户尝试的以下代码仅得到展开后的元素数组,未完成统计:
const res2 = myArr.reduce((acc, x) => { acc.push(x.split(", ")); return acc.flat(); }, []); console.log(res2) // [ 'a', 'b', 'c', 'a', 'b', 'a', 'b', 'b', 'a', 'a', 'a', 'b', 'c', 'd' ]
单次reduce实现方案
完全可以只用一次reduce()完成统计,核心是将累加器设为计数对象,在每次迭代中直接处理分割后的元素并更新计数:
const myArr = ["a, b, c", "a", "b", "a, b", "b", "a", "a", "a, b, c, d"]; const countResult = myArr.reduce((acc, currentStr) => { // 将当前字符串分割为单个元素的数组 const elements = currentStr.split(", "); // 遍历每个元素,更新计数 elements.forEach(el => { // 若元素已存在则计数+1,否则初始化为1 acc[el] = (acc[el] || 0) + 1; }); return acc; }, {}); // 初始累加器为空对象 console.log(countResult); // { a: 6, b: 5, c: 2, d: 1 }
方案说明
- 累加器
acc从空对象开始,直接存储每个元素的计数,无需额外创建中间数组 - 每次迭代处理数组中的一个字符串,先分割为单个元素,再遍历这些元素更新计数
- 逻辑简洁高效,避免了
map()和flat()带来的额外数组内存开销
内容的提问来源于stack exchange,提问作者Emman
相关产品推荐
相关产品推荐

