1. 主页 > 小妙招

JS数组求众数的最简单实现,附代码示例

(拍大腿)哎!有没有遇到过这样的问题?给你一个数组 [2,3,5,3,3,2,2],让你找出出现次数最多的数字?这时候你可能会抓耳挠腮——这玩意儿到底该怎么算啊?别慌,今天咱们就用最接地气的方式,把这道题给盘明白!


一、到底啥叫"众数"?

举个栗子啊,就像你们班考试,全班50个人里有30个都考了80分,那80分就是这次考试的众数。说白了,??众数就是一组数据中出现次数最多的那个值??。不过要注意哦,有时候可能有多个值出现次数一样多,这时候就会有多个众数。

(挠头)那在JS里具体怎么操作呢?别急,咱们一步步来。


二、手把手教你实现

第一步:先准备个计数器

咱们可以用普通对象当计数器,就像这样:

javascript复制
let arr = [2,3,5,3,3,2,2];
let counter = {};

for(let num of arr) {
    // 如果这个数字还没记录过,就先记个0
    if(!counter[num]) counter[num] = 0;
    // 每次遇到就+1
    counter[num]++;
}

这时候counter对象就会变成:

javascript复制
{ '2': 3, '3': 3, '5': 1 }

(敲黑板)看到了吧?2和3都出现了3次,所以这俩都是众数。


第二步:找出最大出现次数

这时候需要找最大的那个值:

javascript复制
let maxCount = Math.max(...Object.values(counter));  // 3

第三步:收集所有符合条件的数

最后遍历counter对象:

javascript复制
let result = [];
for(let key in counter) {
    if(counter[key] === maxCount) {
        result.push(Number(key));  // 记得转成数字类型
    }
}

这时候result就是[2,3]啦!


三、完整代码一锅端

把上面的步骤打包成函数:

javascript复制
function findMode(arr) {
    // 第一步:统计次数
    const counter = {};
    for(const num of arr) {
        counter[num] = (counter[num] || 0) + 1;
    }
    
    // 第二步:找最大次数
    const maxCount = Math.max(...Object.values(counter));
    
    // 第三步:收集结果
    const result = [];
    for(const num in counter) {
        if(counter[num] === maxCount) {
            result.push(Number(num));
        }
    }
    
    return result.length === 1 ? result[0] : result;
}

// 测试一下
console.log(findMode([2,3,5,3,3,2,2]));  // [2,3]
console.log(findMode([1,2,3,4,5]));      // [1,2,3,4,5]

(突然想到)对了!这里有个小陷阱要注意:当所有元素出现次数都为1时,整个数组都会被当作众数返回,这个逻辑是故意这么设计的,因为确实每个数都是出现次数最多的嘛!


四、优化代码的小技巧

技巧1:用Map代替对象

如果数组里有特殊类型的数据,比如对象、NaN,用Map会更靠谱:

javascript复制
const counter = new Map();
arr.forEach(num => {
    counter.set(num, (counter.get(num) || 0) + 1);
});

技巧2:一行代码统计次数

用reduce方法装个逼:

javascript复制
const counter = arr.reduce((acc, num) => {
    acc[num] = (acc[num] || 0) + 1;
    return acc;
}, {});

五、实战中的常见问题

  1. ??空数组怎么办???
    记得在最开始加个判断:

    javascript复制
    if(arr.length === 0) throw new Error("数组不能为空!");
  2. ??处理大数组会卡吗???
    这个方案时间复杂度是O(n),处理百万级数据都没问题。不过要注意??Object.values??这个方法在超大数据量下可能会有点吃力。

  3. ??能不能用ES6新语法???
    当然可以!比如用展开运算符处理Map:

    javascript复制
    const maxCount = Math.max(...counter.values());

六、个人踩坑经验谈

刚开始学的时候,我总想着用各种高阶函数装逼,结果搞出一堆花里胡哨的代码。后来被组长骂了才知道,??代码的可读性比炫技更重要??。比如这个求众数的需求,用最朴实的for循环反而更容易维护。

还有一次遇到个奇葩需求:要同时返回众数和出现次数。这时候只要稍微改改返回值就行:

javascript复制
return {
    mode: result,
    count: maxCount
};

(托腮)说到底啊,编程就像做菜,同样的食材用不同的做法都能做出美味。关键是要根据实际情况选择最合适的烹饪方式。下次遇到类似的问题,希望你能自信地说:"这题我会!" 然后刷刷刷写出既简洁又高效的代码。记住了,编程没有标准答案,能解决问题的代码就是好代码!

本文由嘻道妙招独家原创,未经允许,严禁转载