JS代码片段-如何找出数组中出现次数最多的元素

        在许多应用场景中,我们需要找到数组中出现次数最多的元素。这里的关键点就是要如何统计每个元素出现的次数。在JS中,使用数组的reduce方法,无论是原始值还是对象值,都可以比较容易地实现。

        下面,我们分别来看下如何在数组中查找最多次数的原始值和对象值。

1.找出数组中出现最多次数的原始类型元素

        原始值很容易进行比较和计算频率。我们可以使用Array.prototype.reduce()来创建一个对象,这个对象的键为数组的唯一值,值为它们的频率。

注意,这里可以使用空值合并运算符(??)来初始化每个键的值为0(如果不存在,设为0),并在遇到相同值时将其加1。

        最后,再使用Object.entries()和Array.prototype.reduce()来找到出现次数最多的值。

const mostFrequent = arr =>
  Object.entries(
    arr.reduce((a, v) => {
      a[v] = (a[v] ?? 0) + 1;
      return a;
    }, {})
  ).reduce((a, v) => (v[1] >= a[1] ? v : a), [null, 0])[0];

mostFrequent(['a', 'b', 'a', 'c', 'a', 'a', 'b']); // 'a'

        注:Object.entries():将对象转为键值的二维数组,类似 [[k1,v1],[k2, v2]]。

               Array.prototype.reduce():简要来说,就是用于遍历数组,可以将上一次遍历的返回值用于本次遍历。第一个参数为上次遍历的返回值,第二个参数为本次遍历的值。

2.找出数组中出现最多次数的对象类型元素

        在处理对象时,可以使用相同的方法,但需要一个映射函数来提取想要比较的值。由于原始值可以使用===运算符进行比较,可以提供一个默认的映射函数,该函数返回值本身。这样就可以使相同的实现同时适用于原始值和对象值。

const mostFrequent = (arr, mapFn = x => x) =>
  Object.entries(
    arr.reduce((a, v) => {
      const k = mapFn(v);
      a[k] = (a[k] ?? 0) + 1;
      return a;
    }, {})
  ).reduce((a, v) => (v[1] >= a[1] ? v : a), [null, 0])[0];

const people = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 28 },
  { name: 'John', age: 30 },
];
mostFrequent(people, p => p.age); // '30'

const nums = [1, 2, 3, 1, 2, 1];
mostFrequent(nums); // '1'

3.改进型

        上面两种实现方式都有一个问题:返回值是字符串,不管数组本身是原始值还是其他类型。为了解决这个问题,可以使用Map来存储元素出现的次数,然后找到出现次数最多的值,因为Map中的键可以是任何类型。

        这里需要改动的就是创建一个Map作为Array.prototype.reduce()的累加器,并使用Map.prototype.get()和Map.prototype.set()与之交互。最后,可以使用展开运算符(...)将Map转换为数组再找到出现最多的值。

const mostFrequent = (arr, mapFn = x => x) =>
  [
    ...arr.reduce((a, v) => {
      const k = mapFn(v);
      a.set(k, (a.get(k) ?? 0) + 1);
      return a;
    }, new Map()),
  ].reduce((a, v) => (v[1] >= a[1] ? v : a), [null, 0])[0];

const people = [
  { name: 'John', age: 30 },
  { name: 'Jane', age: 28 },
  { name: 'John', age: 30 },
];
mostFrequent(people, p => p.age); // 30

const nums = [1, 2, 3, 1, 2, 1];
mostFrequent(nums); // 1

 您在访问GitHub时是否经常无法访问?那么除了使用VPN以外,不妨到开源精选(Awesome Top)上逛一逛,这里精选了优秀的开源项目,在这里不仅可以看到项目Readme和官网地址,还可以了解一些开源的热门榜单和趋势!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农界的小蜜蜂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值