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

IT技术 javascript duplicates
2021-01-26 06:20:25

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

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

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

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

注意我不关心找到重复项,只想要布尔结果是否数组包含重复项。

6个回答

如果您有 ES2015 环境(在撰写本文时:io.js、IE11、Chrome、Firefox、WebKit nightly),那么以下将起作用,并且速度会很快(即 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;
}

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

请编辑。我无法编辑,因为我更改的字符不超过 6 个。
2021-03-17 06:20:25
因此,“如果您只需要数组中的字符串值”在答案之前。
2021-03-27 06:20:25
关于你给出的第一个例子。验证不是完全相反吗?如果您的函数是 named hasDuplicates,那么它应该检查集合的大小在转换过程中是否真的缩小了,对吗?因此布尔运算符应该是!==而不是===
2021-03-30 06:20:25
普通 JS 版本返回true以下数组:[1, '1']
2021-04-06 06:20:25
根据MDN IE11 不支持第一个示例中使用的构造函数
2021-04-12 06:20:25

您可以使用 SET 删除重复项并进行比较,如果将数组复制到集合中,它将删除任何重复项。然后只需将数组的长度与集合的大小进行比较。

function hasDuplicates(a) {

  const noDups = new Set(a);

  return a.length !== noDups.size;
}

另一种方法(也适用于数组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 编辑:函数现在可用于简单检查或返回重复值数组

@Domenic:是的,应该提到它。编辑以规避原始数组的突变。
2021-03-20 06:20:25
@Domenic:针对 null/NaN/[+/-]Infinity 进行更正,请参阅编辑。
2021-03-23 06:20:25
值得注意的非showstopper问题:1)改变要排序的原始数组;2) 不区分null, NaN, Infinity, +Infinity, 和-Infinity; 3) 如果对象具有相同的自有属性,则它们被认为是相等的,即使它们具有不同的原型。
2021-04-06 06:20:25
@Domenic:问题 3) 实际上对我来说不是问题,因为这正是我想要的。我不关心原型,只关心值。
2021-04-14 06:20:25

您可以利用indexOflastIndexOf如果两个索引不相同,则您有重复。

function containsDuplicates(a) {
  for (let i = 0; i < a.length; i++) {
    if (a.indexOf(a[i]) !== a.lastIndexOf(a[i])) {
      return true
    }
  }
  return false
}

如果您正在处理简单的值,您可以使用array.some()indexOf()

例如让我们说vals["b", "a", "a", "c"]

const allUnique = !vals.some((v, i) => vals.indexOf(v) < i);

some()如果任何表达式返回真,则返回真。在这里,我们将迭代值(从索引 0)并调用 indexOf(),它将返回给定项目第一次出现的索引(如果不在数组中,则返回 -1)。如果它的 id 小于当前的 id,那么它之前必须至少有一个相同的值。因此迭代 3 将返回 true,因为首先在索引 1 处找到“a”(在索引 2 处)。