admin管理员组

文章数量:1125969

I need to check a JavaScript array to see if there are any duplicate values. What's the easiest way to do this? I just need to find what the duplicated values are - I don't actually need their indexes or how many times they are duplicated.

I know I can loop through the array and check all the other values for a match, but it seems like there should be an easier way.

Similar question:

  • Get all unique values in a JavaScript array (remove duplicates)

I need to check a JavaScript array to see if there are any duplicate values. What's the easiest way to do this? I just need to find what the duplicated values are - I don't actually need their indexes or how many times they are duplicated.

I know I can loop through the array and check all the other values for a match, but it seems like there should be an easier way.

Similar question:

  • Get all unique values in a JavaScript array (remove duplicates)
Share Improve this question edited Oct 16, 2019 at 17:16 Dharman 33.2k27 gold badges101 silver badges146 bronze badges asked May 8, 2009 at 16:48 Scott SaundersScott Saunders 30.4k14 gold badges58 silver badges66 bronze badges 3
  • 30 There seems to be years of confusion about what this question asks. I needed to know what elements in the array were duplicated: "I just need to find what the duplicated values are". The correct answer should NOT remove duplicates from the array. That's the inverse of what I wanted: a list of the duplicates, not a list of unique elements. – Scott Saunders Commented Feb 22, 2013 at 15:47
  • github.com/lodash/lodash/issues/4852#issuecomment-666366511 I would add this as an answer, but given the length of answers, it would never be seen – lonewarrior556 Commented Jul 30, 2020 at 14:44
  • Christ, it seems no one knows how to read. Four pages of "answers" and most don't even answer the question (or even work!) – user3932000 Commented Apr 8, 2024 at 9:44
Add a comment  | 

99 Answers 99

Reset to default 1 2 3 4 Next 375

You could sort the array and then run through it and then see if the next (or previous) index is the same as the current. Assuming your sort algorithm is good, this should be less than O(n2):

const findDuplicates = (arr) => {
  let sorted_arr = arr.slice().sort(); // You can define the comparing function here. 
  // JS by default uses a crappy string compare.
  // (we use slice to clone the array so the
  // original array won't be modified)
  let results = [];
  for (let i = 0; i < sorted_arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
      results.push(sorted_arr[i]);
    }
  }
  return results;
}

let duplicatedArray = [9, 9, 111, 2, 3, 4, 4, 5, 7];
console.log(`The duplicates in ${duplicatedArray} are ${findDuplicates(duplicatedArray)}`);

In case, if you are to return as a function for duplicates. This is for similar type of case.

Reference: https://stackoverflow.com/a/57532964/8119511

If you want to elimate the duplicates, try this great solution:

function eliminateDuplicates(arr) {
  var i,
      len = arr.length,
      out = [],
      obj = {};

  for (i = 0; i < len; i++) {
    obj[arr[i]] = 0;
  }
  for (i in obj) {
    out.push(i);
  }
  return out;
}

console.log(eliminateDuplicates([1,6,7,3,6,8,1,3,4,5,1,7,2,6]))

Source: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/

This is my answer from the duplicate thread (!):

When writing this entry 2014 - all examples were for-loops or jQuery. JavaScript has the perfect tools for this: sort, map and reduce.

Find duplicate items

var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

const uniq = names
  .map((name) => {
    return {
      count: 1,
      name: name
    };
  })
  .reduce((result, b) => {
    result[b.name] = (result[b.name] || 0) + b.count;

    return result;
  }, {});
const duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1);

console.log(duplicates); // [ 'Nancy' ]

More functional syntax:

@Dmytro-Laptin pointed out some code that can be removed. This is a more compact version of the same code. Using some ES6 tricks and higher-order functions:

const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];
const count = names =>
  names.reduce((result, value) => ({ ...result,
    [value]: (result[value] || 0) + 1
  }), {}); // don't forget to initialize the accumulator
const duplicates = dict =>
  Object.keys(dict).filter((a) => dict[a] > 1);

console.log(count(names)); // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
console.log(duplicates(count(names))); // [ 'Nancy' ]

UPDATED: Short one-liner to get the duplicates:

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

To get the array without duplicates simply invert the condition:

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

Note that this answer’s main goal is to be short. If you need something performant for a big array, one possible solution is to sort your array first (if it is sortable) then do the following to get the same kind of results as above:

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

Here is an example for a 1 000 000 integers array:

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

On my AMD Ryzen 7 5700G dev machine it outputs:

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

As pointed out in the comments both the short solution and the performant solution will return an array with several time the same duplicate if it occurs more than once in the original array:

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

If unique duplicates are wanted then a function like

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

can be used so that duplicates([1, 1, 1, 2, 2, 2, 2]) returns [1, 2].


When all you need is to check that there are no duplicates as asked in this question you can use the every() method:

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

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

Note that every() doesn't work for IE 8 and below.

Find duplicate values in an array

This should be one of the shortest ways to actually find duplicate values in an array. As specifically asked for by the OP, this does not remove duplicates but finds them.

var input = [1, 2, 3, 1, 3, 1];

var duplicates = input.reduce(function(acc, el, i, arr) {
  if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
}, []);

document.write(duplicates); // = 1,3 (actual array == [1, 3])

// Or, using Sets (about 4 times faster)

var duplicates = Array.from(items.reduce((acc, v, i, arr) {
  return arr.indexOf(v) !== i ? acc.add(v) : acc;
}, new Set()))

This doesn't need sorting or any third party framework. It also doesn't need manual loops. It works with every value indexOf() (or to be clearer: the strict comparision operator) supports.

Because of reduce() and indexOf() it needs at least IE 9.

You can add this function, or tweak it and add it to Javascript's Array prototype:

Array.prototype.unique = function () {
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++)
    {
        for(var x = 0, y = r.length; x < y; x++)
        {
            if(r[x]==this[i])
            {
                alert('this is a DUPE!');
                continue o;
            }
        }
        r[r.length] = this[i];
    }
    return r;
}

var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
var unique = arr.unique();
alert(unique);

UPDATED: The following uses an optimized combined strategy. It optimizes primitive lookups to benefit from hash O(1) lookup time (running unique on an array of primitives is O(n)). Object lookups are optimized by tagging objects with a unique id while iterating through so so identifying duplicate objects is also O(1) per item and O(n) for the whole list. The only exception is items that are frozen, but those are rare and a fallback is provided using an array and indexOf.

var unique = function(){
  var hasOwn = {}.hasOwnProperty,
      toString = {}.toString,
      uids = {};

  function uid(){
    var key = Math.random().toString(36).slice(2);
    return key in uids ? uid() : uids[key] = key;
  }

  function unique(array){
    var strings = {}, numbers = {}, others = {},
        tagged = [], failed = [],
        count = 0, i = array.length,
        item, type;

    var id = uid();

    while (i--) {
      item = array[i];
      type = typeof item;
      if (item == null || type !== 'object' && type !== 'function') {
        // primitive
        switch (type) {
          case 'string': strings[item] = true; break;
          case 'number': numbers[item] = true; break;
          default: others[item] = item; break;
        }
      } else {
        // object
        if (!hasOwn.call(item, id)) {
          try {
            item[id] = true;
            tagged[count++] = item;
          } catch (e){
            if (failed.indexOf(item) === -1)
              failed[failed.length] = item;
          }
        }
      }
    }

    // remove the tags
    while (count--)
      delete tagged[count][id];

    tagged = tagged.concat(failed);
    count = tagged.length;

    // append primitives to results
    for (i in strings)
      if (hasOwn.call(strings, i))
        tagged[count++] = i;

    for (i in numbers)
      if (hasOwn.call(numbers, i))
        tagged[count++] = +i;

    for (i in others)
      if (hasOwn.call(others, i))
        tagged[count++] = others[i];

    return tagged;
  }

  return unique;
}();

If you have ES6 Collections available, then there is a much simpler and significantly faster version. (shim for IE9+ and other browsers here: https://github.com/Benvie/ES6-Harmony-Collections-Shim)

function unique(array){
  var seen = new Set;
  return array.filter(function(item){
    if (!seen.has(item)) {
      seen.add(item);
      return true;
    }
  });
}
var a = ["a","a","b","c","c"];

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

This should get you what you want, Just the duplicates.

function find_duplicates(arr) {
  var len=arr.length,
      out=[],
      counts={};

  for (var i=0;i<len;i++) {
    var item = arr[i];
    counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
    if (counts[item] === 2) {
      out.push(item);
    }
  }

  return out;
}

find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.

Find non-unique values from 3 arrays (or more):

ES2015

//          

本文标签: