我需要检查一个JavaScript数组,看看是否有任何重复的值。最简单的方法是什么?我只需要找到复制的值是什么——实际上我不需要它们的索引,也不需要它们复制了多少次。

我知道我可以循环遍历数组并检查所有其他值是否匹配,但似乎应该有更简单的方法。

类似的问题:

获取JavaScript数组中所有唯一的值(删除重复值)


当前回答

我试过了,你会得到唯一的元素和在两个不同数组中重复的元素。

复杂度O (n)

let start = [1,1,2,1,3,4,5,6,5,5]; start.sort(); const unique=[]; const repeat = []; let ii=-1 ; for(let i =0 ; i<start.length; i++){ if(start[i]===start[i-1]){ if(repeat[ii]!==start[i-1]){ repeat.push(start[i-1]); ii++; } } else { if(i+1<start.length){ if(start[i]!==start[i+1]){ unique.push(start[i]); } } else if(i===start.length-1){ unique.push(start[i]); } } } console.log(unique) ; console.log(repeat);

其他回答

你可以使用排序、筛选和集合来做到这一点。

Var数= [1,2,3,4,5,6,7,8,1,2,3,4,5,3,4]; var numbersSorted = numbers.sort(); 令result = numbers。Filter ((e, i) => numbers[i] == numbers[i+1]); 结果=[…]新设置(结果)]; console.log(结果);

var input = ['a', 'b', 'a', 'c', 'c'],
    duplicates = [],
    i, j;
for (i = 0, j = input.length; i < j; i++) {
  if (duplicates.indexOf(input[i]) === -1 && input.indexOf(input[i], i+1) !== -1) {
    duplicates.push(input[i]);
  }
}

console.log(duplicates);

我认为下面是完成你要求的最简单和最快的O(n)方法:

function getDuplicates( arr ) {
  var i, value;
  var all = {};
  var duplicates = [];

  for( i=0; i<arr.length; i++ ) {
    value = arr[i];
    if( all[value] ) {
      duplicates.push( value );
      all[value] = false;
    } else if( typeof all[value] == "undefined" ) {
      all[value] = true;
    }
  }

  return duplicates;
}

对于ES5或更高版本:

function getDuplicates( arr ) {
  var all = {};
  return arr.reduce(function( duplicates, value ) {
    if( all[value] ) {
      duplicates.push(value);
      all[value] = false;
    } else if( typeof all[value] == "undefined" ) {
      all[value] = true;
    }
    return duplicates;
  }, []);
}
var a= [1, 2,2,3,3,4,4,4];
var m=[];
var n = [];
a.forEach(function(e) {
  if(m.indexOf(e)=== -1) {
    m.push(e);
}else if(n.indexOf(e)=== -1){
    n.push(e);
}

});

更新:简短的一行程序,以获得副本:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]

要获得没有重复项的数组,只需反转条件:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]

注意,这个答案的主要目标是简短。如果你需要一个大数组的性能,一个可能的解决方案是先排序你的数组(如果它是可排序的),然后执行以下操作来获得与上面相同的结果:

myHugeSortedArray.filter((e, i, a) => a[i-1] === e)

下面是一个1 000 000个整数数组的例子:

const myHugeIntArrayWithDuplicates =
  [...Array(1_000_000).keys()]
  // adding two 0 and four 9 duplicates
  .fill(0, 2, 4).fill(9, 10, 14)

console.time("time")
console.log(
  myHugeIntArrayWithDuplicates
  // a possible sorting method for integers
  .sort((a, b) => a > b ? 1 : -1)
  .filter((e, i, a) => a[i-1] === e)
)
console.timeEnd("time")

在我的AMD Ryzen 7 5700G开发机上输出:

[ 0, 0, 9, 9, 9, 9 ]
time: 22.738ms

正如在评论中指出的那样,短解决方案和性能解决方案都将返回一个具有多次相同副本的数组,如果它在原始数组中出现多次:

[1, 1, 1, 2, 2, 2, 2].filter((e, i, a) => a.indexOf(e) !== i) // [1, 1, 2, 2, 2]

如果需要唯一的副本,则函数为

function duplicates(arr) {
  return [...new Set(arr.filter((e, i, a) => a.indexOf(e) !== i))]
}

可以使用duplicate([1, 1, 1, 2, 2, 2, 2])返回[1,2]。


当你所需要的只是检查是否像这个问题中要求的那样没有重复时,你可以使用every()方法:

[1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true

[1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false

注意,every()在ie8及以下版本中不起作用。