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

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

类似的问题:

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


当前回答

返回副本并保留数据类型。

具有O(4n)性能

const dupes = arr => {
  const map = arr.reduce((map, curr) => {
    return (map.set(curr, (map.get(curr) || 0) + 1), map)
  }, new Map());

  return Array.from(map).filter(([key, val])=> val > 1).map(([key, val]) => key)
}

具有O(2n)性能

const dupes = arr => {
  const map = arr.reduce((map, curr) => {
    return (map.set(curr, (map.get(curr) || 0) + 1), map)
  }, new Map());

  const dupes_ = [];
  for (let [key, val] of map.entries()) {
    if (val > 1) dupes_.push(key);
  }
  return dupes_;
}

其他回答

排名较高的答案有一些固有的问题,包括使用遗留的javascript,不正确的排序或只支持2个重复的项目。

这里有一个解决这些问题的现代解决方案:

const arrayNonUniq = array => {
    if (!Array.isArray(array)) {
        throw new TypeError("An array must be provided!")
    }

    return array.filter((value, index) => array.indexOf(value) === index && array.lastIndexOf(value) !== index)
}

arrayNonUniq([1, 1, 2, 3, 3])
//=> [1, 3]

arrayNonUniq(["foo", "foo", "bar", "foo"])
//=> ['foo']

你也可以使用npm包array-non-uniq。

var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})

我更喜欢函数法。

function removeDuplicates(links) {
    return _.reduce(links, function(list, elem) { 
        if (list.indexOf(elem) == -1) {
            list.push(elem);
        }   
        return list;
    }, []);
}

它使用下划线,但Array也有一个reduce函数

大多数答案我都不喜欢。

为什么?太复杂,代码太多,效率低下,许多代码没有回答问题,即找到重复项(而不是给出一个没有重复项的数组)。

Next函数返回所有副本:

function GetDuplicates(arr) {
  var i, out=[], obj={};
  for (i=0; i < arr.length; i++) 
    obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]);
  return out;
}  

因为在大多数情况下,返回所有重复值是没有用的,而只是告诉存在哪些重复值。在这种情况下,返回一个具有唯一重复项的数组;-)

function GetDuplicates(arr) {
  var i, out=[], obj={};
  for (i=0; i < arr.length; i++)
    obj[arr[i]] == undefined ? obj[arr[i]] ++ : out.push(arr[i]);
  return GetUnique(out);
}

function GetUnique(arr) {
  return $.grep(arr, function(elem, index) {
    return index == $.inArray(elem, arr);
  });
}

也许其他人也这么想。

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);