JavaScript ES6 用reduce实现字符串数组去重与计数、占比统计
ES6 数组频次统计实现(基于reduce)
实现思路
- 首先利用
reduce的累加能力遍历原数组,先完成字符频次的键值对映射统计,匹配效率远高于直接在结果数组里循环查找。 - 拿到频次映射后,遍历映射项生成目标结构的对象数组,直接通过「当前字符出现次数 / 原数组总长度」计算对应占比即可。
推荐实现(性能更优)
// 原输入数组 const sourceArr = ["e", "e", "e", "e", "a", "e", "e", "a", "e", "e", "e", "e", "e", "o", "a", "e", "r", "e", "e", "e", "o", "e", "u"]; // reduce遍历统计频次,最终得到 { e:16, a:3, o:2, r:1, u:1 } 的键值映射 const countMap = sourceArr.reduce((acc, cur) => { acc[cur] = (acc[cur] || 0) + 1; return acc; }, {}); // 将频次映射转换为目标结构,同步计算占比 const result = Object.entries(countMap).map(([letter, duplicates]) => ({ letter, duplicates, percentage: duplicates / sourceArr.length }));
单轮reduce写法(可直接返回目标数组)
如果希望不额外拆分遍历步骤,也可以直接在reduce的累加器里维护最终的目标数组,写法如下:
const sourceArr = ["e", "e", "e", "e", "a", "e", "e", "a", "e", "e", "e", "e", "e", "o", "a", "e", "r", "e", "e", "e", "o", "e", "u"]; const totalLength = sourceArr.length; const result = sourceArr.reduce((acc, cur) => { // 匹配累加数组中是否已存在当前字符 const existItem = acc.find(item => item.letter === cur); if (existItem) { // 已存在则计数+1,同步更新占比 existItem.duplicates += 1; existItem.percentage = existItem.duplicates / totalLength; } else { // 不存在则新增对应项 acc.push({ letter: cur, duplicates: 1, percentage: 1 / totalLength }); } return acc; }, []);
注意:这种单轮直接返回结果数组的写法,在短数组下可以正常运行,但因为每轮都需要遍历累加数组匹配字符,当原数组长度较大时性能远不如「先对象做频次映射,再转数组」的写法,实际项目更推荐前者。
另外你给出的预期结果中,r对应的对象漏写了收尾逗号,属于语法笔误,上述实现会自动修正格式问题。
内容的提问来源于stack exchange,提问作者tkahn
相关产品推荐
相关产品推荐

