从数组中删除重复元素

99
例如,我有这样一个数组;
var arr = [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10]

我的目的是从数组中删除重复元素,并得到最终数组,例如:

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

如何在JavaScript中实现这一点?

注意:数组未排序,值可以是任意顺序。


你可以循环遍历数组并将所有元素复制到一个映射中。 - Devolus
@Devolus 这仅适用于字符串和数字,您不能将对象或数组用作索引键。 - Umur Kontacı
1
这是一个解决方案,但也是一种暴力解决方案。有更聪明(高效)的方法吗? - Mehmet Ince
1
对数组进行排序,迭代,如果与上一个元素不同,则将元素推入新数组。 - DarthJDG
1
@Devolus:但JavaScript不像Java。 - Felix Kling
显示剩余2条评论
5个回答

265

使用Array.filter更容易:

var unique = arr.filter(function(elem, index, self) {
    return index === self.indexOf(elem);
})

9
这个方法为什么这么有效?能否解释一下,最坏情况运行时间取决于indexOf方法如何运作,如果它是线性时间,则最坏情况时间为O(n^2)。 - abkds
1
@MehmetInce 这根本不是“高效”的,它的时间复杂度是O(n^2)。 - Dragos Rizescu
有人能详细解释一下这个魔法是如何工作的吗? :-) - MadPhysicist
5
.filter()遍历整个数组,并仅返回回调函数返回true的元素。 .indexOf()返回数组中最左边元素的索引。如果存在重复元素,则当其索引与最左边元素的索引进行比较时,它们肯定会被移除。更多信息请查看https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Array/filter :) @MadPhysicist - Niccolò Campolungo
1
这个答案对于非常小的列表仍然是可以的。它的优点是代码非常简单,因此不太可能出现错误,并且阅读起来比使用辅助存储的代码要轻松得多。但它的灵活性较差:如果您想基于列表中项目的单个字段消除重复项,则无法工作,而另一种解决方案则很容易适应这种情况。 - Arthur Tacca
显示剩余7条评论

24

由于元素尚未排序,您无需构建地图,这里有一个快速解决方案:

var newarr = [arr[0]];
for (var i=1; i<arr.length; i++) {
   if (arr[i]!=arr[i-1]) newarr.push(arr[i]);
}

如果您的数组没有排序,您将使用 map :

var newarr = (function(arr){
  var m = {}, newarr = []
  for (var i=0; i<arr.length; i++) {
    var v = arr[i];
    if (!m[v]) {
      newarr.push(v);
      m[v]=true;
    }
  }
  return newarr;
})(arr);

请注意,这远比被接受的答案快得多。


1
数组并不总是排序的。 - Mehmet Ince
比那更简单让你的方法更简单一些var m = [];arr.forEach( v => m[v]=true );var newarr = Object.keys(m);很容易,对吧? - pPanda_beta
1
这是一个很好的答案。不过我会使用ES6 Set而不是对象,这样列表中的项就不必是字符串了。(显然,在回答写出来之前,这不是一个选项。) - Arthur Tacca
这在无序数组中也非常快。谢谢! - German
非常棒的回答!;) - Britto

11

6
您可以尝试使用jQuery这样做。
 var arr = [1,2,2,3,4,5,5,5,6,7,7,8,9,10,10];
    var uniqueVals = [];
    $.each(arr, function(i, el){
        if($.inArray(el, uniqueVals) === -1) uniqueVals.push(el);
    });

5
尝试以下来自从数组中删除重复项(简单版)的方法:
Array.prototype.removeDuplicates = function (){
  var temp=new Array();
  this.sort();
  for(i=0;i<this.length;i++){
    if(this[i]==this[i+1]) {continue}
    temp[temp.length]=this[i];
  }
  return temp;
} 

编辑:

这段代码不需要排序:

Array.prototype.removeDuplicates = function (){
  var temp=new Array();
  label:for(i=0;i<this.length;i++){
        for(var j=0; j<temp.length;j++ ){//check duplicates
            if(temp[j]==this[i])//skip if already present 
               continue label;      
        }
        temp[temp.length] = this[i];
  }
  return temp;
 } 

但不是已测试过的代码!

1
这个函数不仅会删除重复的元素,还会进行排序。为何要在Array的原型中添加这样一个特定的函数(对于大多数无法直接排序的数组类型并不适用)? - Denys Séguret
也许更好的做法是测试不等式并且避免使用 continue - Matanya
@Matanya 我正在改进我的答案。 - Grijesh Chauhan
https://dev59.com/iWox5IYBdhLWcg3waziQ - georg
如何使用这些函数,需要传递哪个需要排序的数组。 - Phaneendra Charyulu Kanduri
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接