JavaScript统计数组众数时对象键值递增计数失效问题排查
根因定位
- 核心错误是判断条件的对比对象完全写反了
你代码里现在的判断逻辑是if (reducer[key] === arr[i]),拿已经累加的计数值去和数组元素做相等匹配,根本不是拿对象键代表的原始元素值去匹配数组内容。
拿key='6'的执行流程举例:这个键对应的初始计数值是0,内层遍历数组时,只有当数组元素等于当前计数值才会触发递增:- 遍历到数组索引7位置的0元素时,
0 === 0成立,计数值从0变成1 - 后续遍历到索引8位置的5元素,和当前计数值1不相等,不会再触发递增
所有键的计数在执行时,都会在碰到数组里那个0元素的时候统一触发一次加1,之后再也没有匹配条件触发后续递增,最终所有计数结果都是1,完全达不到统计元素出现次数的目的。
- 遍历到数组索引7位置的0元素时,
最小改动修正
把判断条件的对比对象换成对象键本身(注意对象键默认是字符串类型,需要转成数字再和数组里的数字元素比较,避免类型不匹配):
const mode = function(arr) { const reducer = arr.reduce((accumulator, currentValue) => (accumulator[currentValue] = 0, accumulator), {}); for (let key in reducer) { for (let i = 0; i < arr.length; i++) { // 修正点:把转成数字的key和数组元素对比 if (Number(key) === arr[i]) { reducer[key]++; } } } return reducer; };
改完后跑测试数组,'6'对应的计数会正确变为2。
简化优化
你原来的思路是先遍历一遍数组生成全0初始值的计数对象,再两层循环逐个匹配计数,其实完全可以把两次遍历合并成一次,代码更简洁,性能更好:
const mode = function(arr) { return arr.reduce((countMap, currentVal) => { // 键不存在时初始值为0,每匹配一次就累加1 countMap[currentVal] = (countMap[currentVal] || 0) + 1; return countMap; }, {}); }; // 测试输出:{ '0': 1, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 2, '9': 1 }
小提示:如果要基于这个计数结果计算众数,只需要遍历最终的计数对象,找到值最大的那个键对应的数值,就是数组的众数。
内容的提问来源于stack exchange,提问作者sandypockets
相关产品推荐
相关产品推荐

