我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放入新数组。
我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
我需要删除重复项并将唯一值放入新数组。
我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。
类似的问题:
获取数组中的所有非唯一值(即:重复/多次出现)
当前回答
下面的测试比列出的jQuery方法快80%以上(请参见下面的测试)。这是几年前一个类似问题的答案。如果我遇到最初提出这个建议的人,我会记下学分。纯JS。
var temp = {};
for (var i = 0; i < array.length; i++)
temp[array[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
我的测试用例比较:http://jsperf.com/remove-duplicate-array-tests
其他回答
嵌套循环方法,用于删除数组中的重复项并保留元素的原始顺序。
var array = [1, 3, 2, 1, [5], 2, [4]]; // INPUT
var element = 0;
var decrement = array.length - 1;
while(element < array.length) {
while(element < decrement) {
if (array[element] === array[decrement]) {
array.splice(decrement, 1);
decrement--;
} else {
decrement--;
}
}
decrement = array.length - 1;
element++;
}
console.log(array);// [1, 3, 2, [5], [4]]
说明:内部循环将数组的第一个元素与从索引最高的元素开始的所有其他元素进行比较。向第一个元素递减,从阵列中拼接一个副本。
当内部循环完成时,外部循环递增到下一个元素进行比较,并重置数组的新长度。
我已经在其他问题上对消除重复进行了详细的比较,但注意到这是真实的地方,我也想在这里分享一下。
我相信这是最好的方法
var-myArray=[100,200,100,100,200,200,200],reduced=Object.keys(myArray.reduce((p,c)=>(p[c]=true,p),{}));console.log(减少);
好啊尽管这一个是O(n),其他是O(n^2),但我很好奇地看到这个reduce/look up表和filter/indexOf组合之间的基准比较(我选择了非常好的Jetendras实现https://stackoverflow.com/a/37441144/4543207). 我准备了一个100K的项目数组,其中填充了0-9999范围内的随机正整数,并删除了重复项。我重复了10次测试,结果的平均值表明他们在性能上不匹配。
在firefox v47中,reduce和lut:14.85ms vs filter和indexOf:2836ms在铬v51中,reduce和lut:23.90ms vs filter和indexOf:1066ms
好吧,到目前为止还不错。但是,让我们这次在ES6风格中正确地完成它。看起来很酷。。!但到目前为止,它将如何对抗强大的lut解决方案对我来说是一个谜。让我们先看看代码,然后对其进行基准测试。
var-myArray=[100,200,100,100,200,200,200],reduce=[…myArray.reduce((p,c)=>p.set(c,true),new Map()).keys()];console.log(减少);
哇,太短了。。!但表演怎么样。。?它很美。。。由于过滤器/indexOf的重量超过了我们的肩,现在我可以测试范围为0..9999的1M个正整数随机项,以获得10次连续测试的平均值。我可以说这一次是真正的比赛。亲自查看结果:)
var ranar=[],red1=a=>Object.keys(a.reduce((p,c)=>(p[c]=true,p),{})),red2=a=>reduced=[…a.reduce((p,c)=>p.set(c,true),new Map()).keys()],avg1=[],avg2=[],ts=0,te=0,res1=[],res2=[],计数=10;for(变量i=0;i<count;i++){ranar=(new Array(1000000).fill(true)).map(e=>Math.floor(Math.random()*100000));ts=performance.now();res1=红色1(ranar);te=performance.now();平均推力(te ts);ts=performance.now();res2=red2(ranar);te=performance.now();平均推力(te ts);}avg1=avg1。减少((p,c)=>p+c)/计数;avg2=avg2.减少((p,c)=>p+c)/计数;console.log(“reduce&luttake:”+avg1+“msec”);console.log(“map&spread take:”+avg2+“msec”);
你会用哪一个。。?别那么快。。。!不要上当受骗。贴图处于置换状态。现在看。。。在上述所有情况下,我们用范围<n的数字填充一个大小为n的数组。如果我们用随机数0..9999填充大小为100的数组。现在让我们在家看地图游戏。这一次是一个100K项的数组,但随机数范围为0..10M。我们将进行100次连续测试,以平均结果。好的,让我们看看赌注……!<-没有错别字
var ranar=[],red1=a=>Object.keys(a.reduce((p,c)=>(p[c]=true,p),{})),red2=a=>reduced=[…a.reduce((p,c)=>p.set(c,true),new Map()).keys()],avg1=[],avg2=[],ts=0,te=0,res1=[],res2=[],计数=100;for(变量i=0;i<count;i++){ranar=(new Array(100000).fill(true)).map(e=>Math.floor(Math.random()*1000000));ts=performance.now();res1=红色1(ranar);te=performance.now();平均推力(te ts);ts=performance.now();res2=red2(ranar);te=performance.now();平均推力(te ts);}avg1=avg1。减少((p,c)=>p+c)/计数;avg2=avg2.减少((p,c)=>p+c)/计数;console.log(“reduce&luttake:”+avg1+“msec”);console.log(“map&spread take:”+avg2+“msec”);
现在,这是Map()的惊人回归。。!也许现在,当你想删除重复时,你可以做出更好的决定。
好吧,我们现在都很开心。但主角总是在一些掌声中走到最后。我相信你们中的一些人想知道Set对象会做什么。既然我们对ES6开放,而且我们知道Map是前几场比赛的赢家,那么让我们将Map与Set进行比较作为决赛。这是一场典型的皇家马德里vs巴塞罗那的比赛。。。还是这样?让我们看看谁会赢得el classico:)
var ranar=[],red1=a=>reduce=[…a.reduce((p,c)=>p.set(c,true),new Map()).keys()],red2=a=>Array.from(新集合(a)),avg1=[],avg2=[],ts=0,te=0,res1=[],res2=[],计数=100;for(变量i=0;i<count;i++){ranar=(new Array(100000).fill(true)).map(e=>Math.floor(Math.random()*100000));ts=performance.now();res1=红色1(ranar);te=performance.now();平均推力(te ts);ts=performance.now();res2=red2(ranar);te=performance.now();平均推力(te ts);}avg1=avg1。减少((p,c)=>p+c)/计数;avg2=avg2.减少((p,c)=>p+c)/计数;console.log(“map&spread take:”+avg1+“msec”);console.log(“set&A.from take:”+avg2+“msec”);
哇!成年男子出乎意料的是,它根本就不是一个古典音乐。更像巴塞罗那FC对阵CA Osasuna:))
ES2015,1-liner,它与map链接良好,但仅适用于整数:
[1, 4, 1].sort().filter((current, next) => current !== next)
[1, 4]
一种简单但有效的技术是将filter方法与filter函数(value,index){return this.indexOf(value)==index}结合使用。
代码示例:
var数据=[2,3,4,5,5,4];var filter=函数(值,索引){return this.indexOf(值)==索引};var filteredData=data.filter(过滤器,数据);document.body.innerHTML=“<pre>”+JSON.stringify(filteredData,null,'\t')+“</pre>”;
另请参见此Fiddle。
var duplicates = function(arr){
var sorted = arr.sort();
var dup = [];
for(var i=0; i<sorted.length; i++){
var rest = sorted.slice(i+1); //slice the rest of array
if(rest.indexOf(sorted[i]) > -1){//do indexOf
if(dup.indexOf(sorted[i]) == -1)
dup.push(sorted[i]);//store it in another arr
}
}
console.log(dup);
}
duplicates(["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"]);