获取 JavaScript 数组中的所有唯一值(删除重复项)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1960473/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get all unique values in a JavaScript array (remove duplicates)
提问by Mottie
I have an array of numbers that I need to make sure are unique. I found the code snippet below on the internet and it works great until the array has a zero in it. I found this other scripthere on Stack Overflow that looks almost exactly like it, but it doesn't fail.
我有一组数字,我需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它运行良好,直到数组中有一个零。我在 Stack Overflow 上发现了另一个脚本,它看起来几乎一模一样,但它并没有失败。
So for the sake of helping me learn, can someone help me determine where the prototype script is going wrong?
所以为了帮助我学习,谁能帮我确定原型脚本哪里出错了?
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;
}
More answers from duplicate question:
重复问题的更多答案:
Similar question:
类似问题:
回答by TLindig
With JavaScript 1.6/ ECMAScript 5you can use the native filtermethod of an Array in the following way to get an array with unique values:
使用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 ); // returns ['a', 1, 2, '1']
The native method filterwill loop through the array and leave only those entries that pass the given callback function onlyUnique.
本机方法filter将遍历数组并只留下那些传递给定回调函数的条目onlyUnique。
onlyUniquechecks, if the given value is the first occurring. If not, it must be a duplicate and will not be copied.
onlyUnique检查给定的值是否是第一次出现。如果不是,它必须是重复的,不会被复制。
This solution works without any extra library like jQuery or prototype.js.
该解决方案无需任何额外的库,如 jQuery 或prototype.js。
It works for arrays with mixed value types too.
它也适用于具有混合值类型的数组。
For old Browsers (<ie9), that do not support the native methods filterand indexOfyou can find work arounds in the MDN documentation for filterand indexOf.
对于旧的浏览器(<IE9),不支持原生的方法filter和indexOf你能找到的MDN文档中的变通过滤器和的indexOf。
If you want to keep the last occurrence of a value, simple replace indexOfby lastIndexOf.
如果要保留最后一次出现的值,只需替换indexOf为lastIndexOf。
With ES6 it could be shorten to this:
使用 ES6,它可以缩短为:
// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i);
// unique is ['a', 1, 2, '1']
Thanks to Camilo Martinfor hint in comment.
感谢Camilo Martin的评论提示。
ES6 has a native object Setto store unique values. To get an array with unique values you could do now this:
ES6 有一个本地对象Set来存储唯一值。要获得具有唯一值的数组,您现在可以执行以下操作:
var myArray = ['a', 1, 'a', 2, '1'];
let unique = [...new Set(myArray)];
// unique is ['a', 1, 2, '1']
The constructor of Settakes an iterable object, like Array, and the spread operator ...transform the set back into an Array. Thanks to Lukas Liesefor hint in comment.
的构造函数Set接受一个可迭代对象,如 Array,并且扩展运算符...将集合转换回一个 Array。感谢Lukas Liese的评论提示。
回答by A.T.
Updated answer for ES6/ES2015: Using the Set, the single line solution is:
ES6/ES2015 的更新答案:使用Set,单行解决方案是:
var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))
Which returns
哪个返回
[4, 5, 6, 3, 2, 23, 1]
As le_msuggested, this can also be shortened using spread operator, like
var uniqueItems = [...new Set(items)]
回答by Max Makhrov
I realise this question has more than 30 answers already. But I've read through all the existing answers first and made my own research.
我意识到这个问题已经有 30 多个答案了。但是我首先阅读了所有现有的答案并进行了自己的研究。
I split all answers to 4 possible solutions:
我将所有答案拆分为 4 种可能的解决方案:
- Use new ES6 feature:
[...new Set( [1, 1, 2] )]; - Use object
{ }to prevent duplicates - Use helper array
[ ] - Use
filter + indexOf
- 使用新的 ES6 特性:
[...new Set( [1, 1, 2] )]; - 使用对象
{ }防止重复 - 使用辅助数组
[ ] - 用
filter + indexOf
Here's sample codes found in answers:
以下是答案中的示例代码:
Use new ES6 feature: [...new Set( [1, 1, 2] )];
使用新的 ES6 特性: [...new Set( [1, 1, 2] )];
function uniqueArray0(array) {
var result = Array.from(new Set(array));
return result
}
Use object { }to prevent duplicates
使用对象{ }防止重复
function uniqueArray1( ar ) {
var j = {};
ar.forEach( function(v) {
j[v+ '::' + typeof v] = v;
});
return Object.keys(j).map(function(v){
return j[v];
});
}
Use helper array [ ]
使用辅助数组 [ ]
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;
}
Use filter + indexOf
用 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;
}
And I wondered which one is faster. I've made sample Google Sheetto test functions. Note: ECMA 6 is not avaliable in Google Sheets, so I can't test it.
我想知道哪个更快。我制作了示例 Google Sheet来测试功能。注意:ECMA 6 在 Google 表格中不可用,因此我无法对其进行测试。
I expected to see that code using object { }will win because it uses hash. So I'm glad that tests showed best results for this algorithm in Chrome and IE. Thanks to @rab for the code.
我希望看到使用 object 的代码{ }会获胜,因为它使用了哈希。所以我很高兴测试在 Chrome 和 IE 中显示了该算法的最佳结果。感谢@rab 提供代码。
回答by kornfridge
You can also use underscore.js.
您也可以使用underscore.js。
console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>
which will return:
这将返回:
[1, 2, 3, 4]
回答by Vamsi
One Liner, Pure JavaScript
单行,纯 JavaScript
With ES6 syntax
使用 ES6 语法
list = list.filter((x, i, a) => a.indexOf(x) == i)
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")
With ES5 syntax
使用 ES5 语法
list = list.filter(function (x, i, a) {
return a.indexOf(x) == i;
});
Browser Compatibility: IE9+
浏览器兼容性:IE9+
回答by Mottie
I have since found a nice method that uses jQuery
从那以后,我找到了一个使用 jQuery 的好方法
arr = $.grep(arr, function(v, k){
return $.inArray(v ,arr) === k;
});
Note: This code was pulled from Paul Irish's duck punching post- I forgot to give credit :P
注意:此代码是从Paul Irish 的鸭子打孔帖子中提取的- 我忘了给信用:P
回答by Torsten Becker
Shortest solution with ES6: [...new Set( [1, 1, 2] )];
ES6 的最短解决方案: [...new Set( [1, 1, 2] )];
Or if you want to modify the Array prototype (like in the original question):
或者,如果您想修改 Array 原型(如原始问题):
Array.prototype.getUnique = function() {
return [...new Set( [this] )];
};
EcmaScript 6 is only partially implementedin modern browsers at the moment (Aug. 2015), but Babelhas become very popular for transpiling ES6 (and even ES7) back to ES5. That way you can write ES6 code today!
目前(2015 年 8 月),EcmaScript 6 仅在现代浏览器中部分实现,但Babel在将 ES6(甚至 ES7)转换回 ES5 方面变得非常流行。这样你今天就可以编写 ES6 代码了!
If you're wondering what the ...means, it's called the spread operator. From MDN: ?The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected?. Because a Set is an iterable (and can only have unique values), the spread operator will expand the Set to fill the array.
如果您想知道这...意味着什么,它被称为传播运算符。来自MDN:?展开运算符允许在需要多个参数(用于函数调用)或多个元素(用于数组文字)的地方扩展表达式?。因为 Set 是可迭代的(并且只能具有唯一值),所以扩展运算符将扩展 Set 以填充数组。
Resources for learning ES6:
学习 ES6 的资源:
- Exploring ES6by Dr. Axel Rauschmayer
- Search “ES6”from JS weekly newsletters
- ES6 in depth articlesfrom the Mozilla Hacks blog
回答by Pedro L.
Simplest solution:
最简单的解决方案:
var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log([...new Set(arr)]);
Or:
或者:
var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log(Array.from(new Set(arr)));
回答by Joeytje50
The simplest, and fastest(in Chrome) way of doing this:
最简单、最快(在 Chrome 中)的方法:
Array.prototype.unique = function() {
var a = [];
for (var i=0, l=this.length; i<l; i++)
if (a.indexOf(this[i]) === -1)
a.push(this[i]);
return a;
}
Simply goes through every item in the array, tests if that item is already in the list, and if it's not, push to the array that gets returned.
只需遍历数组中的每个项目,测试该项目是否已经在列表中,如果不是,则推送到返回的数组。
According to jsPerf, this function is the fastest of the ones I could find anywhere- feel free to add your own though.
根据 jsPerf,这个函数是我在任何地方都能找到的最快的函数——尽管可以随意添加你自己的函数。
The non-prototype version:
非原型版本:
function uniques(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;
}
Sorting
排序
When also needing to sort the array, the following is the fastest:
当还需要对数组进行排序时,以下是最快的:
Array.prototype.sortUnique = function() {
this.sort();
var last_i;
for (var i=0;i<this.length;i++)
if ((last_i = this.lastIndexOf(this[i])) !== i)
this.splice(i+1, last_i-i);
return this;
}
or non-prototype:
或非原型:
function sortUnique(arr) {
arr.sort();
var last_i;
for (var i=0;i<arr.length;i++)
if ((last_i = arr.lastIndexOf(arr[i])) !== i)
arr.splice(i+1, last_i-i);
return arr;
}
This is also faster than the above methodin most non-chrome browsers.
在大多数非 Chrome 浏览器中,这也比上述方法更快。
回答by cocco
PERFORMANCE ONLY! this code is probably 10X faster than all the codes in here*works on all browsers and also has the lowest memory impact.... and more
只为性能!这段代码可能比这里的所有代码快 10 倍* 适用于所有浏览器,并且对内存的影响最小......等等
if you don't need to reuse the old array;btw do the necessary other operations before you convert it to unique here is probably the fastest way to do this, also very short.
如果您不需要重用旧数组;顺便说一句,在将其转换为 unique 之前执行必要的其他操作可能是最快的方法,也很短。
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
then you can try this
那么你可以试试这个
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];
function toUnique(a, b, c) { //array,placeholder,placeholder
b = a.length;
while (c = --b)
while (c--) a[b] !== a[c] || a.splice(c, 1);
return a // not needed ;)
}
console.log(toUnique(array));
//[3, 4, 5, 6, 7, 8, 9, 0, 2, 1]
I came up with this function reading this article...
我想出了这个功能阅读这篇文章...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
I don't like the for loop. it has to many parameters.i like the while-- loop. while is the fastest loop in all browsers except the one we all like so much... chrome.
我不喜欢 for 循环。它有很多参数。我喜欢 while-- 循环。while 是所有浏览器中最快的循环,除了我们都非常喜欢的那个……chrome。
anyway i wrote the first function that uses while.And yep it's a little faster than the function found in the article.but not enough.unique2()
无论如何,我编写了第一个使用 while 的函数。是的,它比文章中找到的函数快一点。但还不够。unique2()
next step use modern js.Object.keysi replaced the other for loop with js1.7's Object.keys...
a little faster and shorter (in chrome 2x faster) ;). Not enough!.unique3().
下一步使用现代js。Object.keys我用 js1.7 的 Object.keys 替换了另一个 for 循环......更快更短(在 chrome 中快 2 倍);)。不够!。unique3().
at this point i was thinking about what i really need in MY unique function.
i don't need the old array, i want a fast function.
so i used 2 while loops + splice.unique4()
在这一点上,我正在考虑我在我的独特功能中真正需要什么。我不需要旧数组,我想要一个快速的功能。所以我用了2个while循环+拼接。unique4()
Useless to say that i was impressed.
不用说我印象深刻。
chrome:the usual 150,000 operations per second jumped to 1,800,000 operations per second.
chrome:通常的每秒 150,000 次操作跃升至每秒 1,800,000 次操作。
ie:80,000 op/s vs 3,500,000 op/s
即:80,000 op/s vs 3,500,000 op/s
ios:18,000 op/s vs 170,000 op/s
ios:18,000 op/s vs 170,000 op/s
safari:80,000 op/s vs 6,000,000 op/s
safari:80,000 op/s vs 6,000,000 op/s
Proofhttp://jsperf.com/wguor better use console.time... microtime... whatever
证明http://jsperf.com/wgu或更好地使用 console.time ... microtime ... 随便
unique5()is just to show you what happens if you want to keep the old array.
unique5()只是为了向您展示如果您想保留旧数组会发生什么。
Don't use Array.prototypeif yu don't know what your doing.
i just did alot of copy and past.
Use Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})if you want to create a native prototype.example: https://stackoverflow.com/a/20463021/2450730
Array.prototype如果你不知道你在做什么,就不要使用。我只是做了很多复制和过去。Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})如果要创建本机原型,请使用。示例:https: //stackoverflow.com/a/20463021/2450730
Demohttp://jsfiddle.net/46S7g/
NOTE: your old array is destroyed/becomestheunique after this operation.
注意:您的旧阵列在此操作后被销毁/成为唯一。
if you can't read the code above ask, read a javascript book or here are some explainations about shorter code. https://stackoverflow.com/a/21353032/2450730
如果你看不懂上面的代码,请阅读一本 javascript 书籍,或者这里有一些关于较短代码的解释。https://stackoverflow.com/a/21353032/2450730
some are using indexOf... don't ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh
有些正在使用indexOf......不要...... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh
for empty arrays
对于空数组
!array.length||toUnique(array);


