在 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) 不区分null
、NaN
、Infinity
、+Infinity
和-Infinity
; 3) 如果对象具有相同的自身属性,则认为它们是相等的,即使它们具有不同的原型。
@Domenic:是的,应该提到它。编辑以规避原始数组的突变。
@Domenic:已针对 null/NaN/[+/-]Infinity 进行了更正,请参阅编辑。
@Domenic: Issue 3) 实际上对我来说不是问题,因为这正是我想要的。我不关心原型,只关心值。【参考方案4】:
您可以利用indexOf
和lastIndexOf
。如果两个索引不相同,则您有重复。
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中执行if语句来检查JSON数组是不是为空?