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

Posted

技术标签:

【中文标题】在 Javascript 中,如何检查数组是不是有重复值?【英文标题】:In Javascript, how do I check if an array has duplicate values?在 Javascript 中,如何检查数组是否有重复值? 【发布时间】:2011-11-14 15:37:38 【问题描述】:

可能重复:Easiest way to find duplicate values in a javascript array

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

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

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

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

【问题讨论】:

这里是:***.com/questions/840781/… 我不想删除重复的列表。我只想知道一个列表中是否有重复项。 这个问题不是重复的。由于@user847495 只是想检查是否存在重复项,因此该解决方案比查找所有重复项所需的解决方案更快/更容易。例如,您可以这样做:codr.io/v/bvzxhqm 使用下划线,简单技巧var test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) // some code 不是标记问题的重复。在标记问题之前请注意。 【参考方案1】:

如果您有一个 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(n2) 而不是 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 “哈希表”(即对象)只有字符串键。这意味着我们失去了 in 的 O(1) 查找时间,而获得了 indexOf 的 O(n) 查找时间。

【讨论】:

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

您可以使用 SET 删除重复项并进行比较,如果将数组复制到一个集合中,它将删除所有重复项。然后简单地比较数组的长度和集合的大小。

function hasDuplicates(a) 

  const noDups = new Set(a);

  return a.length !== noDups.size;

【讨论】:

【参考方案3】:

另一种方法(也适用于数组中的对象/数组元素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

See also...

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

【讨论】:

值得关注的非显示性问题:1) 改变要排序的原始数组; 2) 不区分nullNaNInfinity+Infinity-Infinity; 3) 如果对象具有相同的自身属性,则认为它们是相等的,即使它们具有不同的原型。 @Domenic:是的,应该提到它。编辑以规避原始数组的突变。 @Domenic:已针对 null/NaN/[+/-]Infinity 进行了更正,请参阅编辑。 @Domenic: Issue 3) 实际上对我来说不是问题,因为这正是我想要的。我不关心原型,只关心值。【参考方案4】:

您可以利用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

【讨论】:

【参考方案5】:

使用 ES6 的单线解决方案

const arr1 = ['hello','goodbye','hey'] 
const arr2 = ['hello','goodbye','hello'] 

const hasDuplicates = (arr) => arr.length !== new Set(arr).size;
console.log(hasDuplicates(arr1)) //return false because no duplicates exist
console.log(hasDuplicates(arr2)) //return true because duplicates exist

const s1 = ['hello','goodbye','hey'].some((e, i, arr) => arr.indexOf(e) !== i)
const s2 = ['hello','goodbye','hello'].some((e, i, arr) => arr.indexOf(e) !== i);

console.log(s1) //return false because no duplicates exist
console.log(s2) //return true because duplicates exist

【讨论】:

FYI - Set 有一个 .size 属性,所以你不必传播到一个数组中来获取 .length【参考方案6】:

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

例如,假设vals["b", "a", "a", "c"]

const allUnique = !vals.some((v, i) => vals.indexOf(v) < i);
如果 any 表达式返回 true,

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

【讨论】:

【参考方案7】:

很简单,你可以使用Array.prototype.every函数

function isUnique(arr) 
  const isAllUniqueItems = input.every((value, index, arr) => 
    return arr.indexOf(value) === index; //check if any duplicate value is in other index
  );

  return isAllUniqueItems;

【讨论】:

【参考方案8】:

使用Set 的解决方案的一个好处是O(1) 在查找列表中现有项目时的性能,而不必循环返回。

使用Some 的解决方案的一个好处是在及早发现重复项时会短路,因此当条件已满足时,您不必继续评估数组的其余部分。

结合两者的一个解决方案是增量构建一个集合,如果当前元素存在于集合中,则提前终止,否则添加它并移动到下一个元素。

const hasDuplicates = (arr) => 
  let set = new Set()
  return arr.some(el => 
    if (set.has(el)) return true
    set.add(el)
  )


hasDuplicates(["a","b","b"]) // true
hasDuplicates(["a","b","c"]) // false

根据JSBench.me,应该可以很好地适应各种用例。 set size 方法在没有欺骗的情况下最快,检查 some + indexOf 在很早的欺骗情况下是最快的,但是这个解决方案在两种情况下都表现良好,使其成为一个很好的全方位实现。

【讨论】:

【参考方案9】:
function hasAllUniqueChars( s ) 
    for(let c=0; c<s.length; c++)
        for(let d=c+1; d<s.length; d++)
            if((s[c]==s[d]))
                return false;
            
        
    
    return true;

【讨论】:

欢迎来到 ***。如果你能解释你的答案而不是只发布一些代码,那就太好了。谢谢!【参考方案10】:

好吧,我在互联网上为你做了一些搜索,我找到了这个方便的链接。

Easiest way to find duplicate values in a JavaScript array

您可以将上述链接中提供的示例代码(由“swilliams”提供)适应您的解决方案。

【讨论】:

以上是关于在 Javascript 中,如何检查数组是不是有重复值?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 Javascript 中是不是存在字符串/数组/对象? [复制]

如何根据 JavaScript 中的值检查对象是不是在数组中?

如何检查数组是不是是Javascript中的空数组数组

如何在javascript中执行if语句来检查JSON数组是不是为空?

如何检查一个字符串数组是不是包含 JavaScript 中的一个字符串? [复制]

如何检查字符串是不是包含 JavaScript 预定义数组中存在的子字符串?