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

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

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

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

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

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

228351 次浏览

如果你有一个 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;
}

我们使用“ hash table”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)查找时间。

另一种方法(也适用于数组 < b > 1 中的 object/array 元素)可以是 < b > 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 编辑:函数现在可以用于简单检查或返回一个重复值数组

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

function hasDuplicates(a) {


const noDups = new Set(a);


return a.length !== noDups.size;
}
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;
}

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

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

很简单,你可以使用 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;
}

具有 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

使用 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,对于各种不同的用例,应该能够很好地预先形成。集合大小方法在没有受骗的情况下是最快的,而检查一些 + indexOf 在很早受骗的情况下是最快的,但是这个解决方案在两种情况下都表现良好,使其成为一个全面的好实现。