计算数组元素的出现次数/频率

IT技术 javascript arrays count element
2021-02-05 22:52:17

在 Javascript 中,我试图获取一个初始数值数组并计算其中的元素。理想情况下,结果将是两个新数组,第一个指定每个唯一元素,第二个包含每个元素出现的次数。但是,我愿意接受有关输出格式的建议。

例如,如果初始数组是:

5, 5, 5, 2, 2, 2, 2, 2, 9, 4

然后将创建两个新数组。第一个将包含每个唯一元素的名称:

5, 2, 9, 4

第二个将包含该元素在初始数组中出现的次数:

3, 5, 1, 1

因为数字 5 在初始数组中出现了 3 次,所以数字 2 出现了 5 次,而 9 和 4 都出现了一次。

我已经搜索了很多解决方案,但似乎没有任何效果,而且我自己尝试过的一切都变得异常复杂。任何帮助,将不胜感激!

谢谢 :)

6个回答

您可以使用对象来保存结果:

const arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
const counts = {};

for (const num of arr) {
  counts[num] = counts[num] ? counts[num] + 1 : 1;
}

console.log(counts[5], counts[2], counts[9], counts[4]);

所以,现在您的counts对象可以告诉您特定数字的计数是多少:

console.log(counts[5]); // logs '3'

如果要获取成员数组,只需使用keys()函数

keys(counts); // returns ["5", "2", "9", "4"]
对于问题中的特定示例,这是正确的,但对于谷歌员工而言,值得指出的是,对于更广泛的使用而言,这并不总是一种安全的技术。将值存储为对象键来计算它们意味着您将这些值转换为字符串,然后计算该值。[5, "5"]只会说你有"5"两次。或者计算一些不同对象的实例只会告诉你有很多[object Object]. 等等等等。
2021-03-12 22:52:17
然后我如何过滤返回的对象以显示数字的最高到最低或最低到最高的计数
2021-03-12 22:52:17
同样,我也喜欢counts[num] = (counts[num] || 0) + 1这样你只需要counts[num]在那里的那一行两次而不是三次。
2021-03-16 22:52:17
需要指出的是,该Object.keys()功能只支持IE9+、FF4+、SF5+、CH6+,Opera不支持。我认为这里最大的障碍是IE9+
2021-03-28 22:52:17
这是一个很好的答案。这很容易抽象为一个函数,该函数接受一个数组并返回一个“计数”对象。
2021-04-03 22:52:17

const occurrences = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
  return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
}, {});

console.log(occurrences) // => {2: 5, 4: 1, 5: 3, 9: 1}

谢谢,非常好的解决方案;) ...并获取“键”和“值”数组: const keys = Object.keys(a); const values = Object.values(a);
2021-03-11 22:52:17
简写:acc[curr] = (acc[curr] || 0) + 1而不是使用if/else. 你可以检查下面的答案
2021-03-29 22:52:17

const arr = [2, 2, 5, 2, 2, 2, 4, 5, 5, 9];

function foo (array) {
  let a = [],
    b = [],
    arr = [...array], // clone array so we don't change the original when using .sort()
    prev;

  arr.sort();
  for (let element of arr) {
    if (element !== prev) {
      a.push(element);
      b.push(1);
    }
    else ++b[b.length - 1];
    prev = element;
  }

  return [a, b];
}

const result = foo(arr);
console.log('[' + result[0] + ']','[' + result[1] + ']')
console.log(arr)

对于小数组,就地排序比创建关联数组更快。
2021-03-13 22:52:17
@ŠimeVidas 我添加了一个免责声明Array.sort,因为错过这个事实让我在真正的代码中绊倒了。(很容易天真地将它视为复制,因为它返回已排序的数组。)
2021-03-20 22:52:17
如果没有来自第三方库的不错的高级原语,我通常会像reduce答案一样实现它我正要提交这样的答案,但我看到它已经存在了。尽管如此,counts[num] = counts[num] ? counts[num]+1 : 1答案也有效(相当于if(!result[a[i]])result[a[i]]=0答案,它更优雅但不太容易阅读);可以修改此答案以使用 for 循环的“更好”版本,可能是第三方 for 循环,但我有点忽略了这一点,因为遗憾的是,基于标准索引的 for 循环是默认值。
2021-03-24 22:52:17
同意@ninjagecko。dictionary会更好。是我对另一种方法的回答。
2021-03-26 22:52:17
有排序数组的副作用(副作用是不好的),排序也是O(N log(N)),优雅的增益是不值得的
2021-04-04 22:52:17

如果使用下划线或 lodash,这是最简单的方法:

_.countBy(array);

这样:

_.countBy([5, 5, 5, 2, 2, 2, 2, 2, 9, 4])
=> Object {2: 5, 4: 1, 5: 3, 9: 1}

正如其他人所指出的那样,然后您可以对结果执行_.keys()_.values()函数以分别获取唯一数字及其出现次数。但以我的经验,原始对象要容易得多。

值得注意的是,使用 countBy 它只包含列表中存在的项目,因此如果您想计算列表中可能不存在的项目,则需要处理异常。或者使用lodash滤波器长度是这样的:filter([true, true, true, false], function(m){return m==true}).length如果不存在任何值,这将仅返回 0。
2021-03-17 22:52:17
值得补充的是你需要: const _ = require("lodash")
2021-03-28 22:52:17

一行 ES6 解决方案。使用对象作为地图的许多答案,但我看不到任何人使用实际地图

const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());

使用map.keys()获得独特的元素

使用map.values()来获取事件

使用map.entries()以获得对[元件,频率]

var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]

const map = arr.reduce((acc, e) => acc.set(e, (acc.get(e) || 0) + 1), new Map());

console.info([...map.keys()])
console.info([...map.values()])
console.info([...map.entries()])