获取 JavaScript 数组中的所有唯一值(删除重复项)

IT技术 javascript unique arrays
2020-12-16 23:36:26

我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它运行良好,直到数组中有一个零。在 Stack Overflow 上发现了另一个脚本,它看起来几乎完全一样,但它并没有失败。

所以为了帮助我学习,谁能帮我确定原型脚本哪里出错了?

Array.prototype.getUnique = function() {
 var o = {}, a = [], i, e;
 for (i = 0; e = this[i]; i++) {o[e] = 1};
 for (e in o) {a.push (e)};
 return a;
}

重复问题的更多答案:

类似问题:

6个回答

使用JavaScript 1.6 / ECMAScript 5,您可以通过filter以下方式使用数组的本机方法来获取具有唯一值的数组:

function onlyUnique(value, index, self) {
  return self.indexOf(value) === index;
}

// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter(onlyUnique);

console.log(unique); // ['a', 1, 2, '1']

本机方法filter将遍历数组并只留下那些传递给定回调函数的条目onlyUnique

onlyUnique检查给定的值是否是第一次出现。如果不是,它必须是重复的,不会被复制。

该解决方案无需任何额外的库,如 jQuery 或prototype.js。

它也适用于具有混合值类型的数组。

对于旧的浏览器(<IE9),不支持原生的方法filterindexOf你能找到的MDN文档中的变通过滤器的indexOf

如果您想保留最后一次出现的值,只需替换indexOflastIndexOf

使用 ES6 这可以缩短为:

// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i);

console.log(unique); // unique is ['a', 1, 2, '1']

感谢Camilo Martin的评论提示。

ES6 有一个本地对象Set来存储唯一值。要获得具有唯一值的数组,您现在可以执行以下操作:

var myArray = ['a', 1, 'a', 2, '1'];

let unique = [...new Set(myArray)];

console.log(unique); // unique is ['a', 1, 2, '1']

的构造函数Set接受一个可迭代对象,如数组,展开运算符...将集合转换回数组。感谢Lukas Liese的评论提示。

不幸的是,这个解决方案的运行速度会慢得多。你循环了两次,一次使用过滤器,一次使用索引
2021-02-07 23:36:26
let unique_values = [...new Set(random_array)]; developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-02-17 23:36:26
在现代 JS 中:(.filter((v,i,a)=>a.indexOf(v)==i)粗箭头符号)。
2021-02-22 23:36:26

ES6/ES2015 的更新答案:使用Set扩展运算符(感谢le-m),单行解决方案是:

let uniqueItems = [...new Set(items)]

哪个返回

[4, 5, 6, 3, 2, 23, 1]
请注意,如果您使用Set和 添加对象而不是原始值,它将包含对对象的唯一引用因此 set sinlet s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);将返回 this:Set { { Foo: 'Bar' }, { Foo: 'Bar' } }这是一个Set对包含相同值的对象具有唯一对象引用的对象。如果您编写let o = {Foo:"Bar"};然后创建一个具有两个引用的集合,例如:let s2 = new Set([o,o]);,那么 s2 将是Set { { Foo: 'Bar' } }
2021-02-12 23:36:26
如果有人想知道,这也适用于字符串,例如 [...new Set(["apple","apple","orange"])] 结果为 ['apple', 'orange'] 。伟大的!
2021-02-15 23:36:26
请注意,内部数组不起作用 Array.from(new Set([[1,2],[1,2],[1,2,3]]))
2021-02-22 23:36:26

我将所有答案拆分为 4 种可能的解决方案:

  1. 使用对象{ }防止重复
  2. 使用辅助数组 [ ]
  3. filter + indexOf
  4. 奖金!ES6Sets方法。

以下是答案中的示例代码:

使用对象{ }防止重复

function uniqueArray1( ar ) {
  var j = {};

  ar.forEach( function(v) {
    j[v+ '::' + typeof v] = v;
  });

  return Object.keys(j).map(function(v){
    return j[v];
  });
} 

使用辅助数组 [ ]

function uniqueArray2(arr) {
    var a = [];
    for (var i=0, l=arr.length; i<l; i++)
        if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
            a.push(arr[i]);
    return a;
}

filter + indexOf

function uniqueArray3(a) {
  function onlyUnique(value, index, self) { 
      return self.indexOf(value) === index;
  }

  // usage
  var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']

  return unique;
}

使用ES6 [...new Set(a)]

function uniqueArray4(a) {
  return [...new Set(a)];
}

我想知道哪个更快。我制作了示例 Google Sheet来测试功能。注意:ECMA 6 在 Google 表格中不可用,因此我无法对其进行测试。

以下是测试结果: 在此处输入图片说明

我希望看到使用 object 的代码{ }会获胜,因为它使用了哈希。所以我很高兴测试在 Chrome 和 IE 中显示了该算法的最佳结果。感谢@rab 提供代码

2020 年更新

谷歌脚本启用 ES6 引擎。现在我测试了最后一个代码,Sets它看起来比对象方法更快。

马克罗夫,所以这uniqueItems = [...new Set(items)]似乎是所有方法中最快和最简洁的?
2021-03-08 23:36:26

您也可以使用underscore.js

console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>

这将返回:

[1, 2, 3, 4]
@JacobDalton 为什么不呢?在阵列上“顶起某些东西”有什么缺点吗?
2021-02-09 23:36:26
请大家这样做。不要在 Array 原型上添加任何东西。请。
2021-02-28 23:36:26
@JacobDalton 请不要这样做。无需为可以完成的小工作添加额外的库array = [...new Set(array)]
2021-03-07 23:36:26

单行,纯 JavaScript

使用 ES6 语法

list = list.filter((x, i, a) => a.indexOf(x) == i)

x --> item in array
i --> index of item
a --> array reference, (in this case "list")

在此处输入图片说明

使用 ES5 语法

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

浏览器兼容性:IE9+