获取数组中所有非唯一值(即重复/多次出现的值)

542

我需要检查JavaScript数组是否有重复值。最简单的方法是什么?我只需要找出重复的值 - 我不需要它们的索引或重复次数。

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

类似的问题:


29
关于这个问题似乎存在多年的混淆。我需要知道数组中重复的元素:“我只需要找到重复的值是什么”。正确答案不应该从数组中删除重复项。那与我想要的相反:我需要一个重复项的列表,而不是唯一元素的列表。 - Scott Saunders
我会翻译这个答复,但是考虑到回答的长度,它可能永远不会被看到。 - lonewarrior556
98个回答

2
我更喜欢使用函数来完成这个任务。
function removeDuplicates(links) {
    return _.reduce(links, function(list, elem) { 
        if (list.indexOf(elem) == -1) {
            list.push(elem);
        }   
        return list;
    }, []);
}

这里使用了 underscore,但是 Array 也有一个 reduce 函数。


不符合提问者的要求,返回重复项。 - RWC

2

有一种非常简单的方法可以解决这个问题。如果您使用新的“Set”JavaScript命令,它可以将数组作为输入并输出仅包含唯一值的新“Set”。然后,通过比较数组的长度和集合的“size”属性,您可以看到它们是否不同。如果它们不同,那么肯定是由于重复的条目。

var array1 = ['value1','value2','value3','value1']; // contains duplicates
var array2 = ['value1','value2','value3','value4']; // unique values

console.log('array1 contains duplicates = ' + containsDuplicates(array1));
console.log('array2 contains duplicates = ' + containsDuplicates(array2));


function containsDuplicates(passedArray) {
  let mySet = new Set(passedArray);
  if (mySet.size !== passedArray.length) {
    return true;
  }
  return false;
}

如果您运行以上片段,您将得到以下输出。
array1 包含重复项 = true array2 不包含重复项 = false

2

我认为最简单的解决方案就是使用indexOf。

以下是将唯一元素推送到数组的完整示例。

var arr = ['a','b','c','d','a','b','c','d'];
var newA = [];
for(var i = 0; i < arr.length; i++){
    if(newA.indexOf(arr[i]) === -1){
        newA.push(arr[i]);
    }
 }

不符合提问者的要求,返回重复项。 - RWC

1
这是我能想到的简单ES5解决方案之一 -
function duplicates(arr) {
  var duplicatesArr = [],
      uniqueObj = {};

  for (var i = 0; i < arr.length; i++) {
    if( uniqueObj.hasOwnProperty(arr[i]) && duplicatesArr.indexOf( arr[i] ) === -1) {
      duplicatesArr.push( arr[i] );
    }
    else {
      uniqueObj[ arr[i] ] = true;
    }
  }

  return duplicatesArr;
}
/* Input Arr: [1,1,2,2,2,1,3,4,5,3] */
/* OutPut Arr: [1,2,3] */

1

实际上,这个问题有很多错误的答案或需要大量额外内存(如Set)的答案,这真是遗憾。一个简洁明了的解决方案:

function findDuplicates<T>(arr: Array<T>): T[] {
  //If the array has less than 2 elements there are no duplicates
  const n = arr.length;
  if (n < 2)
    return [];
  
  const sorted = arr.sort();
  const result = [];

  //Head
  if (sorted[0] === sorted[1])
    result.push(sorted[0]);

  //Inner (Head :: Inner :: Tail)
  for (let i = 1; i < n-1; i++) {
    const elem = sorted[i];
    if (elem === sorted[i - 1] || elem === sorted[i+1])
      result.push(elem)
  }

  //Tail
  if (sorted[n - 1] == sorted[n - 2])
    result.push(sorted[n - 1]);

  return result;
}

console.dir(findDuplicates(['a', 'a', 'b', 'b']));
console.dir(findDuplicates(['a', 'b']));
console.dir(findDuplicates(['a', 'a', 'a']));
console.dir(findDuplicates(['a']));
console.dir(findDuplicates([]));

1

使用underscore的另一种方法。Numbers是源数组,dupes具有可能重复的值。

var itemcounts = _.countBy(numbers, function (n) { return n; });
var dupes = _.reduce(itemcounts, function (memo, item, idx) {
    if (item > 1)
        memo.push(idx);
    return memo;
}, []);

1
最快的解决方法实际上是使用一个标记。

var values = [4,2,3,1,4]

// solution
const checkDuplicate = list => {
  var hasDuplicate = false;
  list.sort().sort((a, b) => {
    if (a === b) hasDuplicate = true
  })
  return hasDuplicate
}

console.log(checkDuplicate(values))


1
这应该是在数组中查找重复值的最短、最简单的方法之一。

var arr = [1,2,3,4,5,6,7,8,1,2,3,4,5,3,3,4];
var data = arr.filter(function(item,index,arr){
  return arr.indexOf(item) != arr.lastIndexOf(item) && arr.indexOf(item) == index;
})

console.log(data );


1
这是一种使用哈希表计数元素并在计数小于2时过滤数组的单循环方法,因为它返回第一个找到的重复项。
优点:
  • 单循环
  • 使用闭包中的对象进行计数

var array = [5, 0, 2, 1, 2, 3, 3, 4, 4, 8, 6, 7, 9, 4],
    duplicates = array.filter((h => v => (h[v] = (h[v] || 0) + 1) === 2)({}));
    
console.log(duplicates);


我们能否获取重复值及其出现次数,例如 [2, 2, 3, 3, 4, 4, 4] - hoangfin
@meteorzeroo 这是另一个问题,但在这种情况下,您需要事先知道计数是否大于1。也就是说,您需要至少进行两次遍历。 - Nina Scholz

1
你可以利用sortfiltersets来实现这一点。

var numbers = [1,2,3,4,5,6,7,8,1,2,3,4,5,3,3,4];
var numbersSorted = numbers.sort();
let result = numbers.filter((e, i) => numbers[i] == numbers[i+1]);
result = [...new Set(result)];
console.log(result);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接