在Javascript中,如何检查数组是否具有重复值?


95

可能重复:
在javascript数组中查找重复值的最简单方法

如何检查数组是否有重复值?

如果数组中的某些元素相同,则返回true。否则,返回false。

['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist

注意,我不在乎查找重复项,只希望布尔结果是否数组包含重复项。



2
我不希望删除重复项列表。我只想知道列表中是否有重复的对或错。
user847495 2011年

7
这个问题不是重复的。由于@ user847495只想检查是否存在重复项,因此该解决方案比查找所有重复项所需的速度更快/更容易。例如,您可以这样做:codr.io/v/bvzxhqm
alden 2015年

2
使用下划线,简单的技术var test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
西羊

4
与标记的问题不重复。在标记问题之前,请注意。
John Weisz

Answers:


220

如果您拥有ES2015环境(在撰写本文时:io.js,IE11,Chrome,Firefox,WebKit每晚),那么以下各项将起作用并且很快(即O(n)):

function hasDuplicates(array) {
    return (new Set(array)).size !== array.length;
}

如果您只需要数组中的字符串值,则可以执行以下操作:

function hasDuplicates(array) {
    var valuesSoFar = Object.create(null);
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (value in valuesSoFar) {
            return true;
        }
        valuesSoFar[value] = true;
    }
    return false;
}

我们使用“哈希表”,valuesSoFar其键是到目前为止在数组中看到的值。我们使用查找来查找in该值是否已经被发现。如果是这样,我们将退出循环并返回true


如果您需要一个功能不仅仅适用于字符串值,则可以使用以下功能,但性能不佳;它是O(n 2)而不是O(n)。

function hasDuplicates(array) {
    var valuesSoFar = [];
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (valuesSoFar.indexOf(value) !== -1) {
            return true;
        }
        valuesSoFar.push(value);
    }
    return false;
}

区别只是因为,我们使用数组而不是哈希表valuesSoFar,因为JavaScript“哈希表”(即对象)仅具有字符串键。这意味着我们损失了O(1)的查找时间in,而不是O(n)的查找时间indexOf


3
关于您给出的第一个示例。验证不是完全相反吗?如果您的函数名为hasDuplicates,那么它应该检查集合的大小在转换过程中是否实际上缩小了,对吗?因此布尔运算符应!==,而不是===
蒂姆Daubenschütz

请编辑。我更改的字符数不能超过6个,因此无法进行编辑。
TimDaubenschütz,2015年

1
根据MDN, IE11不支持第一个示例中使用的构造函数
adam77 '16

正常的JS版本返回true以下数组:[1, '1']
Kunal,

因此,答案前的“如果只需要数组中的字符串值”。
多米尼克'18

4

另一种方法(同样适用于数组1中的对象/数组元素)可以是2

function chkDuplicates(arr,justCheck){
  var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
  arrtmp.sort();
  while(len--){
   var val = arrtmp[len];
   if (/nul|nan|infini/i.test(String(val))){
     val = String(val);
    }
    if (tmp[JSON.stringify(val)]){
       if (justCheck) {return true;}
       dupes.push(val);
    }
    tmp[JSON.stringify(val)] = true;
  }
  return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true);                           //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true);                //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true);          //=> false
chkDuplicates([1,2,3,4,5,1,2]);                            //=> [1,2]
chkDuplicates([1,2,3,4,5]);                                //=> null

也可以看看...

1需要支持JSON的浏览器,如果不支持,则需要JSON库
2 编辑:函数现在可以用于简单检查或返回重复值的数组


3
值得关注的非showstopper问题:1)更改要排序的原始数组;2)之间不区分nullNaNInfinity+Infinity,和-Infinity; 3)即使对象具有相同的自身属性,即使它们具有不同的原型,也将它们视为相等。
Domenic

1
@Domenic:是的,应该提到它。编辑以规避原始数组的突变。
KooiInc 2011年

@Domenic:已校正为null / NaN / [+/-] Infinity,请参见编辑。
KooiInc 2011年

@Domenic:问题3)对我来说实际上不是问题,因为这正是我想要的。我不在乎原型,只在乎价值。
2015年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.