计算数组中的唯一元素而不进行排序

Gho*_*ool 23 javascript sorting

在JavaScript中,以下内容将查找数组中的元素数.假设数组中至少有一个元素

arr = ["jam", "beef", "cream", "jam"]
arr.sort();
var count = 1;
var results = "";
for (var i = 0; i < arr.length; i++)
{
    if (arr[i] == arr[i+1])
    {
      count +=1;
    }
    else
    {
        results += arr[i] + " --> " + count + " times\n" ;
        count=1;
    }
}
Run Code Online (Sandbox Code Playgroud)

是否可以在不使用sort()或不以任何方式改变数组的情况下执行此操作?我想可能必须重新创建数组,然后可以在新创建的数组上完成排序,但我想知道没有排序的最佳方法是什么.是的,我是一个艺术家,而不是程序员,你的荣誉.

koj*_*iro 44

快速执行此操作的方法是将唯一元素复制到Object中.

var counts = {};
for (var i = 0; i < arr.length; i++) {
    counts[arr[i]] = 1 + (counts[arr[i]] || 0);
}
Run Code Online (Sandbox Code Playgroud)

当此循环完成时,counts对象将具有该数组的每个不同元素的计数.

  • @Bergi被授予,但他们是OP的例子. (3认同)
  • 这是有史以来最伟大的代码.它完全按照我想要的方式完成了比我尝试的线路少得多的线路.但是......这是如何工作的?我无法弄清楚为什么它的工作方式如此. (3认同)
  • `counts[arr[i]]` 可能并不总是被设置。`|| 0` 确保我们得到 0(如果不是)。 (2认同)

Web*_*ner 37

快速的方法是使用一个new Set()对象.

集很棒,我们应该更频繁地使用它们.它们很快,并受Chrome,Firefox,Microsoft Edge和node.js的支持.
- 什么是更快的设置或对象?作者:Andrei Kashcha

a中的项目Set将始终是唯一的,因为它只保留您放入的每个值的一个副本.这是一个使用此属性的函数:

function countUnique(iterable) {
  return new Set(iterable).size;
}

console.log(countUnique('banana')); //=> 3
console.log(countUnique([5,6,5,6])); //=> 2
console.log(countUnique([window, document, window])); //=> 2
Run Code Online (Sandbox Code Playgroud)

这可用于计算任何可迭代中的项(包括Array,String,TypedArray和arguments对象).


Ayu*_*ush 8

为什么不是这样的:

var arr = ["jam", "beef", "cream", "jam"]
var uniqs = arr.reduce((acc, val) => {
  acc[val] = acc[val] === undefined ? 1 : acc[val] += 1;
  return acc;
}, {});
console.log(uniqs)
Run Code Online (Sandbox Code Playgroud)

纯Javascript,在O(n)中运行.除非您的唯一值的数量等于元素的数量(所有元素都是唯一的),否则不会占用太多空间.


Ply*_*ynx 6

此表达式为您提供数组中的所有唯一元素,而不会对其进行变更:

arr.filter(function(v,i) { return i==arr.lastIndexOf(v); })
Run Code Online (Sandbox Code Playgroud)

您可以使用此表达式将其链接以构建结果字符串而无需排序:

.forEach(function(v) {
     results+=v+" --> " + arr.filter(function(w){return w==v;}).length + " times\n";
});
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,过滤器仅包括每个特定元素的最后一个; 在第二种情况下,过滤器包括该类型的所有元素,并.length给出计数.


小智 5

该解决方案相同,但是代码更少。

let counts = {};
arr.forEach(el => counts[el] = 1  + (counts[el] || 0))
Run Code Online (Sandbox Code Playgroud)