我有一个非常简单的JavaScript数组,可能包含也可能不包含重复项。

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

我需要删除重复项并将唯一值放入新数组。

我可以指出我尝试过的所有代码,但我认为它们没有用,因为它们不起作用。我也接受jQuery解决方案。

类似的问题:

获取数组中的所有非唯一值(即:重复/多次出现)


当前回答

解决方案1

Array.prototype.unique = function() {
    var a = [];
    for (i = 0; i < this.length; i++) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }
    return a;
}

解决方案2(使用集合)

Array.prototype.unique = function() {
    return Array.from(new Set(this));
}

Test

var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]

表演

当我在chrome中测试两种实现(有和没有Set)的性能时,我发现有Set的实现要快得多!

Array.prototype.unique1=函数(){变量a=[];对于(i=0;i<this.length;i++){无功电流=此[i];如果(a.indexOf(current)<0)a.push(current);}返回a;}Array.prototype.unique2=函数(){return Array.from(new Set(this));}var x=[];对于(var i=0;i<10000;i++){x.push(“x”+i);x.push(“x”+(i+1));}console.time(“unique1”);console.log(x.unique1());console.timeEnd(“unique1”);console.time(“unique2”);console.log(x.unique2());console.timeEnd(“unique2”);

其他回答

这只是另一种解决方案,但与其他解决方案不同。

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  newArr.sort();
  var finalArr = [];
  for(var i = 0;i<newArr.length;i++) {
   if(!(newArr[i] === newArr[i+1] || newArr[i] === newArr[i-1])) {
     finalArr.push(newArr[i]);
   } 
  }
  return finalArr;
}

我已经在其他问题上对消除重复进行了详细的比较,但注意到这是真实的地方,我也想在这里分享一下。

我相信这是最好的方法

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:))

使用array.filter和.indexOf函数的单行版本:

arr = arr.filter(function (value, index, array) { 
  return array.indexOf(value) === index;
});

除了是一个比当前答案更简单、更简洁的解决方案(减去未来的ES6答案)之外,我还测试了这一点,而且速度也快得多:

var uniqueArray = dupeArray.filter(function(item, i, self){
  return self.lastIndexOf(item) == i;
});

一个警告:Array.lastIndexOf()是在IE9中添加的,所以如果您需要低于这个值,您需要在其他地方查找。

ES2015,1-liner,它与map链接良好,但仅适用于整数:

[1, 4, 1].sort().filter((current, next) => current !== next)

[1, 4]