Get all unique values in a JavaScript array (remove duplicates)
我有一组数字需要确保它们是唯一的。我在互联网上找到了下面的代码片段,它工作得很好,直到数组中有一个零为止。我在这找到了另一个脚本,所以看起来几乎和它一模一样,但它没有失败。
所以为了帮助我学习,有人能帮我确定原型脚本哪里出错了吗?
1 2 3 4 5 6 | 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; } |
重复问题的更多答案:
- 从javascript数组中删除重复项
类似问题:
- 获取数组中出现一次以上(即:不唯一)的所有值
使用javascript 1.6/ecmascript 5,可以使用数组的本机
1 2 3 4 5 6 7 | 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'] |
本机方法
如果给定值是第一个发生的,则
此解决方案不需要任何额外的库(如jquery或prototype.js)即可工作。
它也适用于混合值类型的数组。
对于不支持本机方法 如果要保留最后一次出现的值,只需将 使用ES6,可以缩短为:
1 2 3 4 5 | // 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'] |
感谢卡米洛马丁的评论提示。
ES6有一个本地对象
1 2 3 4 5 | var myArray = ['a', 1, 'a', 2, '1']; let unique = [...new Set(myArray)]; // unique is ['a', 1, 2, '1'] |
更新了ES6/ES2015的答案:使用该集合,单线解决方案是:
1 2 | var items = [4,5,4,6,3,4,5,2,23,1,4,4,4] var uniqueItems = Array.from(new Set(items)) |
哪些回报
1 | [4, 5, 6, 3, 2, 23, 1] |
正如Le_m所建议的,这也可以使用spread操作符来缩短,比如
1 | var uniqueItems = [...new Set(items)] |
您还可以使用underline.js。
1 | console.log(_.uniq([1, 2, 1, 3, 1, 4])); |
1 | <script src="http://underscorejs.org/underscore-min.js"> |
将返回:
1 | [1, 2, 3, 4] |
我知道这个问题已经有30多个答案了。但我先通读了所有现有的答案,并做了自己的研究。
我将所有答案分为4个可能的解决方案:
以下是答案中的示例代码:
使用新的ES6功能:1 2 3 4 | function uniqueArray0(array) { var result = Array.from(new Set(array)); return result } |
使用对象
1 2 3 4 5 6 7 8 9 10 11 | function uniqueArray1( ar ) { var j = {}; ar.forEach( function(v) { j[v+ '::' + typeof v] = v; }); return Object.keys(j).map(function(v){ return j[v]; }); } |
使用辅助数组
1 2 3 4 5 6 7 | 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; } |
使用
1 2 3 4 5 6 7 8 9 10 | 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; } |
我想知道哪一个更快。我已经制作了谷歌表单样本来测试函数。注意:ECMA 6在谷歌表单中不可用,所以我无法测试它。
测试结果如下:
我希望看到使用对象
一行,纯javascript
用ES6语法
1 2 3 | x --> item in array i --> index of item a --> array reference, (in this case"list") |
用ES5语法
1 2 3 | list = list.filter(function (x, i, a) { return a.indexOf(x) == i; }); |
浏览器兼容性:IE9+
从那以后,我发现了一个使用jquery的好方法
1 2 3 | arr = $.grep(arr, function(v, k){ return $.inArray(v ,arr) === k; }); |
注意:这段代码是从保罗·爱尔兰的"打鸭子"帖子中提取出来的-我忘了评分:P
ES6最短解:
或者,如果要修改数组原型(如原始问题):
1 2 3 | Array.prototype.getUnique = function() { return [...new Set( [this] )]; }; |
ECMAScript 6目前(2015年8月)仅在现代浏览器中部分实现,但Babel已经非常流行,将ES6(甚至ES7)重新发布到ES5。这样,您就可以在今天编写ES6代码了!
如果你想知道
学习ES6的资源:
- Axel Rauschmayer博士研究ES6
- 从JS周报中搜索"ES6"
- 来自Mozilla Hacks博客的ES6深度文章
最简单的解决方案:
1 2 | var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1]; console.log([...new Set(arr)]); |
或:
1 2 | var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1]; console.log(Array.from(new Set(arr))); |
最简单、最快(铬合金)的方法:
1 2 3 4 5 6 7 | 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; } |
只需遍历数组中的每个项,测试该项是否已经在列表中,如果没有,则推送到返回的数组。
根据JSPerf的说法,这个函数是我在任何地方都能找到的最快的函数——尽管可以随意添加自己的函数。
非原型版本:
1 2 3 4 5 6 7 | 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; } |
分选
当还需要对数组进行排序时,以下是最快的:
1 2 3 4 5 6 7 8 | 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; } |
或非原型:
1 2 3 4 5 6 7 8 | 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; } |
在大多数非Chrome浏览器中,这也比上面的方法快。
仅限表演!此代码可能比此处所有代码快10倍*适用于所有浏览器,并且内存影响最小…更多
如果不需要重用旧数组,那么在将其转换为唯一数组之前,顺便做一些必要的其他操作,这可能是最快的方法,也非常短。
1 | var array=[1,2,3,4,5,6,7,8,9,0,1,2,1]; |
那你可以试试这个
1 2 3 4 5 6 7 8 9 10 | 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] |
我在阅读这篇文章时想到了这个函数…
我不喜欢for循环。它有很多参数,我喜欢while循环。在所有浏览器中,除了我们都非常喜欢的浏览器外,它是最快的循环…铬。
总之,我编写了第一个使用while的函数。是的,它比本文中找到的函数快一点,但还不够。
下一步使用现代JS.
在这一点上,我在思考我的独特功能到底需要什么。我不需要旧的数组,我想要一个快速函数。所以我用了2个while循环+拼接.
没必要说我印象深刻。
Chrome:通常每秒150000次操作跃升到每秒1800000次操作。
即:80000次/秒vs 3500000次/秒
iOS:18000 op/s对170000 op/s
游猎:80000次/秒vs 6000000次/秒
证明http://jspef.com/wgu或更好地使用console.time…微时间…无论什么
如果你不知道自己在做什么,就不要使用
演示http://jsfiddle.net/46s7g/
注意:在执行此操作后,旧数组将被销毁/成为唯一数组。
如果你不能阅读上面的代码,请阅读一本javascript书,或者这里有一些关于较短代码的解释。https://stackoverflow.com/a/21353032/2450730
有些人正在使用
对于空数组
1 | !array.length||toUnique(array); |
这里的许多答案可能对初学者没有用处。如果一个数组的重复数据消除很困难,他们真的知道原型链,甚至jquery吗?
在现代浏览器中,一个干净而简单的解决方案是将数据存储在一个集合中,该集合被设计为一个唯一值列表。
1 2 | const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford']; const uniqueCars = Array.from(new Set(cars)); |
如果您需要支持旧的Internet Explorer,因而不能使用set,那么一种简单的技术是将项目复制到新的数组中,同时预先检查它们是否已经在新的数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // Create a list of cars, with duplicates. var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford']; // Create a list of unique cars, to put a car in if we haven't already. var uniqueCars = []; // Go through each car, one at a time. cars.forEach(function (car) { // The code within the following block runs only if the // current car does NOT exist in the uniqueCars list // - a.k.a. prevent duplicates if (uniqueCars.indexOf(car) === -1) { // Since we now know we haven't seen this car before, // copy it to the end of the uniqueCars list. uniqueCars.push(car); } }); |
为了使这个可以立即重用,让我们把它放到一个函数中。
1 2 3 4 5 6 7 8 9 10 11 12 13 | function deduplicate(data) { if (data.length > 0) { var result = []; data.forEach(function (elem) { if (result.indexOf(elem) === -1) { result.push(elem); } }); return result; } } |
为了消除重复,我们现在就这么做。
1 | var uniqueCars = deduplicate(cars); |
当函数完成时,
把你喜欢的数组的名字传给它。
1 2 3 4 5 6 7 | ["Defects","Total","Days","City","Defects"].reduce(function(prev, cur) { return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev; }, []); [0,1,2,0,3,2,1,5].reduce(function(prev, cur) { return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev; }, []); |
这个原型
以下是正确的解决方案:
1 2 3 | Array.prototype.unique = function(a){ return function(){ return this.filter(a) } }(function(a,b,c){ return c.indexOf(a,b+1) < 0 }); |
使用:
1 2 3 | var foo; foo = ["1",1,2,3,4,1,"foo"]; foo.unique(); |
以上将产生
我们可以使用ES6设置:
1 2 3 4 | var duplicatedArray = [1, 2, 3, 4, 5, 1, 1, 1, 2, 3, 4]; var uniqueArray = Array.from(new Set(duplicatedArray)); console.log(uniqueArray); |
//输出将为
1 | uniqueArray = [1,2,3,4,5]; |
如果不扩展array.prototype(据说这是一个糟糕的实践)或使用jquery/underline,您可以简单地对数组执行
通过保留最后一个事件:
1 2 3 4 5 6 | function arrayLastUnique(array) { return array.filter(function (a, b, c) { // keeps last occurrence return c.indexOf(a, b + 1) < 0; }); }, |
或第一次出现:
1 2 3 4 5 6 | function arrayFirstUnique(array) { return array.filter(function (a, b, c) { // keeps first occurrence return c.indexOf(a) === b; }); }, |
好吧,它只是JavaScriptECMAScript 5+,这意味着只有IE9+,但它很适合在原生HTML/JS(Windows应用商店应用程序、Firefox OS、Sencha、PhoneGap、Titanium…)中进行开发。
这是因为
如果数组的值为0或任何其他错误值,则
如果您使用的是原型框架,则无需执行"for"循环,您可以使用http://www.prototypejs.org/api/array/uniq,如下所示:
1 | var a = Array.uniq(); |
它将生成一个没有重复项的重复数组。我发现你的问题是在寻找一种方法来计算不同的数组记录,所以
uniq()
我用过
size()
这是我的简单结果。对不起,如果我打错了什么
编辑:如果要转义未定义的记录,可以添加
compact()
之前,像这样:
1 | var a = Array.compact().uniq(); |
1 2 3 4 5 6 | Array.prototype.getUnique = function() { var o = {}, a = [] for (var i = 0; i < this.length; i++) o[this[i]] = 1 for (var e in o) a.push(e) return a } |
魔术
1 | a.filter(e=>!(t[e]=e in t)) |
o(n)性能;我们假设您的数组在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var a1 = [5,6,0,4,9,2,3,5,0,3,4,1,5,4,9]; var a2 = [[2, 17], [2, 17], [2, 17], [1, 12], [5, 9], [1, 12], [6, 2], [1, 12]]; var a3 = ['Mike', 'Adam','Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']; let t={}, nd = a => a.filter(e=>!(t[e]=e in t)); //"stand-alone" version working with global t: // a1.filter((t={},e=>!(t[e]=e in t))); let c= x => console.log(JSON.stringify(x)); c( nd(a1) ); c( nd(a2) ); c( nd(a3) ); |
奇怪的是,以前没有人建议过……要在数组中按对象键(下面的
1 2 3 | const uniqArray = array.filter((obj, idx, arr) => ( arr.findIndex((o) => o.id === obj.id) === idx )) |
我不知道为什么加布里埃尔·席尔维拉这样写这个函数,但是一个简单的形式,对我来说也同样有效,没有缩小是:
1 2 3 4 5 | Array.prototype.unique = function() { return this.filter(function(value, index, array) { return array.indexOf(value, index + 1) < 0; }); }; |
或在咖啡中描述:
1 2 3 4 | Array.prototype.unique = -> this.filter( (value, index, array) -> array.indexOf(value, index + 1) < 0 ) |
在简单方法中查找唯一数组值
1 2 3 4 5 6 7 8 | function arrUnique(a){ var t = []; for(var x = 0; x < a.length; x++){ if(t.indexOf(a[x]) == -1)t.push(a[x]); } return t; } arrUnique([1,4,2,7,1,5,9,2,4,7,2]) // [1, 4, 2, 7, 5, 9] |
相反地,要解决这个问题,在加载数组时没有重复的内容可能会很有用,set对象可以这样做,但在所有浏览器中都不可用。它节省了内存,如果您需要多次查看其内容,它会更高效。
1 2 3 4 5 | Array.prototype.add = function (elem) { if (this.indexOf(elem) == -1) { this.push(elem); } } |
Sample:
1 2 | set = []; [1,3,4,1,2,1,3,3,4,1].forEach(function(x) { set.add(x); }); |
给你的是
来自Shamasis Bhattacharya的博客(o(2n)time complexity):
1 2 3 4 5 6 | Array.prototype.unique = function() { var o = {}, i, l = this.length, r = []; for(i=0; i<l;i+=1) o[this[i]] = this[i]; for(i in o) r.push(o[i]); return r; }; |
来自Paul Irish的博客:jquery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | (function($){ var _old = $.unique; $.unique = function(arr){ // do the default behavior only if we got an array of elements if (!!arr[0].nodeType){ return _old.apply(this,arguments); } else { // reduce the array to contain no dupes via grep/inArray return $.grep(arr,function(v,k){ return $.inArray(v,arr) === k; }); } }; })(jQuery); // in use.. var arr = ['first',7,true,2,7,true,'last','last']; $.unique(arr); // ["first", 7, true, 2,"last"] var arr = [1,2,3,4,5,4,3,2,1]; $.unique(arr); // [1, 2, 3, 4, 5] |
基于ES6的解决方案…
1 2 3 | var arr = [2, 3, 4, 2, 3, 4, 2]; const result = [...new Set(arr)]; console.log(result); |
我有一个稍微不同的问题,我需要从数组中删除具有重复ID属性的对象。这是有效的。
1 2 3 4 5 6 7 8 9 10 11 12 13 | let objArr = [{ id: '123' }, { id: '123' }, { id: '456' }]; objArr = objArr.reduce((acc, cur) => [ ...acc.filter((obj) => obj.id !== cur.id), cur ], []); console.log(objArr); |
如果您对额外的依赖关系还满意,或者您的代码库中已经有了一个库,那么您可以使用lodash(或下划线)从一个数组中删除重复项。
用法
如果您的代码库中没有它,请使用NPM安装它:
1 | npm install lodash |
然后如下使用:
1 2 3 4 5 6 7 8 9 | import _ from 'lodash'; let idArray = _.uniq ([ 1, 2, 3, 3, 3 ]); console.dir(idArray); |
出:
1 | [ 1, 2, 3 ] |
您也可以使用sugar.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [1,2,2,3,1].unique() // => [1,2,3] [{id:5, name:"Jay <hr><P>我发现序列化散列键有助于我为对象工作。</P>[cc lang="javascript"]Array.prototype.getUnique = function() { var hash = {}, result = [], key; for ( var i = 0, l = this.length; i < l; ++i ) { key = JSON.stringify(this[i]); if ( !hash.hasOwnProperty(key) ) { hash[key] = true; result.push(this[i]); } } return result; } |
如果有人使用击倒式JS
1 | ko.utils.arrayGetDistinctValues() |
顺便说一下,我们已经了解了所有的
这行得通。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function getUnique(a) { var b = [a[0]], i, j, tmp; for (i = 1; i < a.length; i++) { tmp = 1; for (j = 0; j < b.length; j++) { if (a[i] == b[j]) { tmp = 0; break; } } if (tmp) { b.push(a[i]); } } return b; } |
Building on other answers, here's another variant that takes an optional flag to choose a strategy (keep first occurrence or keep last):
Without extending
1 2 3 4 5 6 7 8 9 | function unique(arr, keepLast) { return arr.filter(function (value, index, array) { return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index; }); }; // Usage unique(['a', 1, 2, '1', 1, 3, 2, 6]); // -> ['a', 1, 2, '1', 3, 6] unique(['a', 1, 2, '1', 1, 3, 2, 6], true); // -> ['a', '1', 1, 3, 2, 6] |
扩展
1 2 3 4 5 6 7 8 9 | Array.prototype.unique = function (keepLast) { return this.filter(function (value, index, array) { return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index; }); }; // Usage ['a', 1, 2, '1', 1, 3, 2, 6].unique(); // -> ['a', 1, 2, '1', 3, 6] ['a', 1, 2, '1', 1, 3, 2, 6].unique(true); // -> ['a', '1', 1, 3, 2, 6] |
看看这个。jquery提供uniq方法:https://api.jquery.com/jquery.unique/唯一/
1 2 3 4 5 6 7 8 9 10 11 12 13 | var ids_array = [] $.each($(my_elements), function(index, el) { var id = $(this).attr("id") ids_array.push(id) }); var clean_ids_array = jQuery.unique(ids_array) $.each(clean_ids_array, function(index, id) { elment = $("#" + id) // my uniq element // TODO WITH MY ELEMENT }); |
使用对象键创建唯一数组,我尝试了以下操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function uniqueArray( ar ) { var j = {}; ar.forEach( function(v) { j[v+ '::' + typeof v] = v; }); return Object.keys(j).map(function(v){ return j[v]; }); } uniqueArray(["1",1,2,3,4,1,"foo", false, false, null,1]); |
返回
也可以使用jquery
1 2 3 4 5 6 7 8 9 | var a = [1,5,1,6,4,5,2,5,4,3,1,2,6,6,3,3,2,4]; // note: jQuery's filter params are opposite of javascript's native implementation :( var unique = $.makeArray($(a).filter(function(i,itm){ // note: 'index', not 'indexOf' return i == $(a).index(itm); })); // unique: [1, 5, 6, 4, 2, 3] |
最初的答案是:jquery函数从数组中获取所有唯一元素?
使用lodash和identity lambda函数,只需在使用对象之前定义它。
1 2 3 4 | const _ = require('lodash'); ... _.uniqBy([{a:1,b:2},{a:1,b:2},{a:1,b:3}], v=>v.a.toString()+v.b.toString()) _.uniq([1,2,3,3,'a','a','x']) |
并将有:
1 2 | [{a:1,b:2},{a:1,b:3}] [1,2,3,'a','x'] |
(这是最简单的方法)
如果您有强大的reduce方法(&ge;5.1),您可以尝试如下操作:
1 2 3 4 5 | Array.prototype.uniq = function() { return this.reduce(function(sofar, cur) { return sofar.indexOf(cur) < 0 ? sofar.concat([cur]) : sofar; }, []); }; |
这不是最有效的实现(因为
这个不是纯的,它会修改数组,但这是最快的。如果你的速度更快,请写在评论中;)
http://jspef.com/unique-array-wedbeb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Array.prototype.uniq = function(){ for(var i = 0, l = this.length; i < l; ++i){ var item = this[i]; var duplicateIdx = this.indexOf(item, i + 1); while(duplicateIdx != -1) { this.splice(duplicateIdx, 1); duplicateIdx = this.indexOf(item, duplicateIdx); l--; } } return this; } [ "",2,4,"A","abc", "",2,4,"A","abc", "",2,4,"A","abc", "",2,4,"A","abc", "",2,4,"A","abc", "",2,4,"A","abc", "",2,4,"A","abc", "",2,4,"A","abc" ].uniq() // ["",2,4,"A","abc"] |
接受选择器的版本应该非常快速和简洁:
1 2 3 4 5 6 7 | function unique(xs, f) { var seen = {}; return xs.filter(function(x) { var fx = (f && f(x)) || x; return !seen[fx] && (seen[fx] = 1); }); } |
对我来说,当您说唯一值时,这意味着值在数据集中只出现一次。
下面过滤值数组,检查给定值的第一个和最后一个索引是否相等。如果索引相等,则表示该值只能出现一次。
1 2 3 4 5 6 7 | var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5]; var unique = values.filter(function(value) { return values.indexOf(value) === values.lastIndexOf(value); }); console.log(unique); // [3, 6] |
基于我误解问题的反馈,这里有一种替代方法,它将从值数组返回唯一的、非重复的值。
1 2 3 4 5 6 | var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5]; var unique = values.reduce(function(unique, value) { return unique.indexOf(value) === -1 ? unique.concat([value]) : unique; }, []); console.log(unique); // [1, 2, 3, 4, 5, 6] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var numbers = [1, 1, 2, 3, 4, 4]; function unique(dupArray) { return dupArray.reduce(function(previous, num) { if (previous.find(function(item) { return item == num; })) { return previous; } else { previous.push(num); return previous; } }, []) } var check = unique(numbers); console.log(check); |
我知道这已经是死路一条了…但是…没有人提到过linq的javascript实现。然后,可以使用
1 2 3 4 5 | var Linq = require('linq-es2015'); var distinctValues = Linq.asEnumerable(testValues) .Select(x) .distinct() .toArray(); |
1 2 3 4 5 6 7 | var testValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1]; var distinctValues = Enumerable.asEnumerable(testValues) .distinct() .toArray(); console.log(distinctValues); |
1 | <script src="https://npmcdn.com/linq-es5/dist/linq.js"> |
我有一个使用ES6 reduce and find array helper方法删除重复项的解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 | let numbers = [2, 2, 3, 3, 5, 6, 6]; const removeDups = array => { return array.reduce((acc, inc) => { if (!acc.find(i => i === inc)) { acc.push(inc); } return acc; }, []); } console.log(removeDups(numbers)); /// [2,3,5,6] |
这是一个ES6函数,它从对象数组中删除重复项,并按指定的对象属性进行筛选。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | function dedupe(arr = [], fnCheck = _ => _) { const set = new Set(); let len = arr.length; for (let i = 0; i < len; i++) { const primitive = fnCheck(arr[i]); if (set.has(primitive)) { // duplicate, cut it arr.splice(i, 1); i--; len--; } else { // new item, add it set.add(primitive); } } return arr; } const test = [ {video:{slug:"a"}}, {video:{slug:"a"}}, {video:{slug:"b"}}, {video:{slug:"c"}}, {video:{slug:"c"}} ] console.log(dedupe(test, x => x.video.slug)); // [{video:{slug:"a"}}, {video:{slug:"b"}}, {video:{slug:"c"}}] |
1 2 3 4 5 6 7 8 | Array.prototype.unique = function() { var a = [],k = 0,e; for(k=0;e=this[k];k++) if(a.indexOf(e)==-1) a.push(e); return a; } [1,2,3,4,33,23,2,3,22,1].unique(); // return [1,2,3,4,33,23,22] |
另一个解决方案。
我最近需要使排序的列表唯一,我使用过滤器跟踪这样一个对象中的前一项:
1 2 3 4 5 | uniqueArray = sortedArray.filter(function(e) { if(e==this.last) return false; this.last=e; return true; },{last:null}); |
类似于@sergeyz解决方案,但通过使用更多的速记格式(如arrow函数和
1 | my_array.reduce((a,k)=>(a.includes(k)||a.push(k),a),[]) |
这个脚本修改数组,过滤掉重复的值。它适用于数字和字符串。
网址:https://jsfiddle.net/qsdl6y5j/1/
1 2 3 4 5 6 7 8 9 10 11 | Array.prototype.getUnique = function () { var unique = this.filter(function (elem, pos) { return this.indexOf(elem) == pos; }.bind(this)); this.length = 0; this.splice(0, 0, unique); } var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4]; duplicates.getUnique(); alert(duplicates); |
相反,此版本允许您返回一个新数组,该数组具有保持原始值的唯一值(仅传递true)。
https://jsfiddle.net/dj7qxyl7/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | Array.prototype.getUnique = function (createArray) { createArray = createArray === true ? true : false; var temp = JSON.stringify(this); temp = JSON.parse(temp); if (createArray) { var unique = temp.filter(function (elem, pos) { return temp.indexOf(elem) == pos; }.bind(this)); return unique; } else { var unique = this.filter(function (elem, pos) { return this.indexOf(elem) == pos; }.bind(this)); this.length = 0; this.splice(0, 0, unique); } } var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4]; console.log('++++ ovveride') duplicates.getUnique(); console.log(duplicates); console.log('++++ new array') var duplicates2 = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4]; var unique = duplicates2.getUnique(true); console.log(unique); console.log('++++ original') console.log(duplicates2); |
1 2 3 4 | Browser support: Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari Basic support (Yes) 1.5 (1.8) 9 (Yes) (Yes) |
您可以使用Ramda.js(一个功能性的javascript库)来执行此操作:
1 2 | var unique = R.uniq([1, 2, 1, 3, 1, 4]) console.log(unique) |
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"> |
使用字段[2]作为ID生成唯一数组的数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | const arr = [ ['497', 'Q0', 'WTX091-B06-138', '0', '1.000000000', 'GROUP001'], ['497', 'Q0', 'WTX091-B09-92', '1', '0.866899288', 'GROUP001'], ['497', 'Q0', 'WTX091-B09-92', '2', '0.846036819', 'GROUP001'], ['497', 'Q0', 'WTX091-B09-57', '3', '0.835025326', 'GROUP001'], ['497', 'Q0', 'WTX091-B43-79', '4', '0.765068215', 'GROUP001'], ['497', 'Q0', 'WTX091-B43-56', '5', '0.764211464', 'GROUP001'], ['497', 'Q0', 'WTX091-B44-448', '6', '0.761701704', 'GROUP001'], ['497', 'Q0', 'WTX091-B44-12', '7', '0.761701704', 'GROUP001'], ['497', 'Q0', 'WTX091-B49-128', '8', '0.747434800', 'GROUP001'], ['497', 'Q0', 'WTX091-B18-17', '9', '0.746724770', 'GROUP001'], ['497', 'Q0', 'WTX091-B19-374', '10', '0.733379549', 'GROUP001'], ['497', 'Q0', 'WTX091-B19-344', '11', '0.731421782', 'GROUP001'], ['497', 'Q0', 'WTX091-B09-92', '12', '0.726450470', 'GROUP001'], ['497', 'Q0', 'WTX091-B19-174', '13', '0.712757036', 'GROUP001'] ]; arr.filter((val1, idx1, arr) => !!~val1.indexOf(val1[2]) && !(arr.filter((val2, idx2) => !!~val2.indexOf(val1[2]) && idx2 < idx1).length)); console.log(arr); |
如果您有一个对象数组,并且需要一个
1 2 3 4 5 6 | function uniqueBy(field, arr) { return arr.reduce((acc, curr) => { const exists = acc.find(v => v[field] === curr[field]); return exists ? acc : acc.concat(curr); }, []) } |
可以使用数组的helper函数reduce()和some()来获得结果。检查我的代码段:
1 2 3 4 5 6 7 8 9 10 11 | var arrayWithDuplicates = [0, 0, 1, 2, 3, 3, 4, 4, 'a', 'a', '', '', null, null]; var arrayWithUniqueValues = arrayWithDuplicates .reduce((previous, item) => { if(!previous.some(element => element === item)) { previous.push(item) } return previous; }, []); console.log('arrayWithUniqueValues', arrayWithUniqueValues) |
对字符串使用.toString()。
1 2 3 4 5 6 7 8 9 | var givenvalues = [1,2,3,3,4,5,6]; var values = []; for(var i=0; i<givenvalues.length; i++) { if(values.indexOf(givenvalues[i]) == -1) { values[values.length] = givenvalues[i]; } } |
另一个答案,仅仅因为我为我的特定用例写了一个。不管怎样,我碰巧正在对数组进行排序,而且考虑到我正在进行排序,我可以使用它来消除重复。
注意,我的排序处理特定的数据类型,您可能需要一个不同的排序,这取决于您拥有的元素的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var sortAndDedup = function(array) { array.sort(function(a,b){ if(isNaN(a) && isNaN(b)) { return a > b ? 1 : (a < b ? -1 : 0); } if(isNaN(a)) { return 1; } if(isNaN(b)) { return -1; } return a-b; }); var newArray = []; var len = array.length; for(var i=0; i<len; i++){ if(i === 0 || array[i] != array[i-1]){ newArray.push(array[i]); } } }; |
如果顺序不重要,那么我们可以创建一个散列并获取使数组唯一的键。
1 2 3 4 | var ar = [1,3,4,5,5,6,5,6,2,1]; var uarEle = {}; links.forEach(function(a){ uarEle[a] = 1; }); var uar = keys(uarEle) |
UAR将具有唯一的数组元素。
我看了JoeyTje50关于JSPerf的代码,他比较了许多替代方案。他的代码有许多小错误,这在性能和正确性上造成了不同。
更重要的是,他正在一个非常小的阵列上进行测试。我做了一个包含1000个整数的数组。每个整数是0到1000之间的随机整数的100倍。平均约1000个/e=368个副本。结果在JSPERF中。
这是一个更现实的场景,其中可能需要效率。这些变化对声明做出了巨大的改变(特别是被吹捧为"最快"的代码根本就不快)。最明显的赢家是使用散列技术的地方,最好的是
1 2 3 4 5 6 7 8 9 | Array.prototype.getUnique3 = function(){ var u = Object.create(null), a = []; for(var i = 0, l = this.length; i < l; ++i){ if(this[i] in u) continue; a.push(this[i]); u[this[i]] = 1; } return a.length; } |
1 2 3 4 5 6 7 8 9 | var a = [1,4,2,7,1,5,9,2,4,7,2] var b = {}, c = {}; var len = a.length; for(var i=0;i<len;i++){ a[i] in c ? delete b[a[i]] : b[a[i]] = true; c[a[i]] = true; } // b contains all unique elements |
这个解决方案应该非常快,并且在许多情况下都可以工作。
使用object.keys函数
1 2 3 4 | var indexArray = ["hi","welcome","welcome",1,-9]; var keyArray = {}; indexArray.forEach(function(item){ keyArray[item]=null; }); var uniqueArray = Object.keys(keyArray); |
过滤掉未定义和空值,因为大多数时候您不需要它们。
1 | const uniques = myArray.filter(e => e).filter((e, i, a) => a.indexOf(e) === i); |
或
1 | const uniques = [...new Set(myArray.filter(e => e))]; |
有时我需要从一组对象中获得唯一的实例。Lodash看起来是个不错的助手,但我认为过滤数组并不能证明向项目添加依赖项是正确的。
让我们假设在比较属性(例如ID)时比较两个对象的姿势。
既然我们都喜欢一行代码片段,那么就可以这样做:
在我使用对象的用例中,上面的对象答案似乎对我不起作用。
我修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var j = {}; this.forEach( function(v) { var typ = typeof v; var v = (typ === 'object') ? JSON.stringify(v) : v; j[v + '::' + typ] = v; }); return Object.keys(j).map(function(v){ if ( v.indexOf('::object') > -1 ) { return JSON.parse(j[v]); } return j[v]; }); |
现在,对于对象、数组、混合值数组、布尔值数组等,这似乎可以正常工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | (function() { "use strict"; Array.prototype.unique = function unique() { var self = this; return self.filter(function(a) { var that = this; // console.log(that); return !that[a] ? that[a] = true : false; }, {}); } var sampleArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; var distinctArray = sampleArray.unique(); console.log(distinctArray); })(); |
1 | Here is the simple way to solve this problem... |
对于字符串数组:
1 2 3 4 5 6 7 | function removeDuplicatesFromArray(arr) { const unique = {}; arr.forEach((word) => { unique[word] = 1; // it doesn't really matter what goes here }); return Object.keys(unique); } |
如果要就地更改(而不是创建新数组),您只需:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var uniq = function uniq(array) { var len = array.length; while (len--) { if (array.indexOf(array[len]) !== len) { array.splice(len, 1); } } return array; }, myArray = [1, 2, 2, 4, 2]; console.log(uniq(myArray)); // [1, 2, 4]; |
不要引用我的话,但我认为你需要在你的属性名上使用一个字符串,比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Array.prototype.unique=function(){ var cr=[]; this.forEach(function(entry) { if(cr.indexOf(entry)<0){ cr.push(entry); }else{ var index = cr.indexOf(entry); if (index > -1) { cr.splice(index, 1); } } }); return cr; } |
我使用数组reduce作为创建数组唯一性的方法
1 2 3 4 5 6 7 8 9 | Array.prototype.unique = function() { var object = this.reduce(function(h, v) { h[v] = true; return h; }, {}); return Object.keys(object); } console.log(["a","b","c","b","c","a","b"].unique()); // => ["a","b","c"] |