154

Possible Duplicate:
Easiest way to find duplicate values in a javascript array

How do I check if an array has duplicate values?

If some elements in the array are the same, then return true. Otherwise, return false.

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

Notice I don't care about finding the duplication, only want Boolean result whether arrays contains duplications.

Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
user847495
  • 9,831
  • 17
  • 45
  • 48
  • Here it is: http://stackoverflow.com/questions/840781/easiest-way-to-find-duplicate-values-in-a-javascript-array/840808#840808 – Ofer Zelig Sep 11 '11 at 06:06
  • 2
    I don't want a list of duplicates removed. I just want to know true or false if a list has duplicates in it. – user847495 Sep 11 '11 at 06:08
  • The accepted answer for the *exact same question you asked* is your answer. http://stackoverflow.com/questions/840781/easiest-way-to-find-duplicate-values-in-a-javascript-array/840808#840808 – Brian Roach Sep 11 '11 at 06:28
  • http://jsfiddle.net/vol7ron/gfJ28/ – vol7ron Sep 11 '11 at 06:42
  • 9
    This question is not a duplicate. Since @user847495 simply wants to check if duplicates exists, the solution is faster/easier than what's needed to find all occurrences of duplicates. For example, you can do this: http://codr.io/v/bvzxhqm – alden Sep 26 '15 at 16:32
  • 2
    using **underscore** ,simple technique `var test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }` – Sai Ram Mar 03 '16 at 13:16
  • 4
    **Not a duplicate of the marked question.** Please pay attention before marking questions as such. – John Weisz Sep 02 '16 at 10:08
  • Using underscore.js it is simple use if(arrayA.length === _.uniq(ArrayA).length){ // do your work} --> if true all are distinct else not distinct – SUDARSHAN BHALERAO Mar 28 '17 at 05:21

11 Answers11

327

If you have an ES2015 environment (as of this writing: io.js, IE11, Chrome, Firefox, WebKit nightly), then the following will work, and will be fast (viz. O(n)):

function hasDuplicates(array) {
    return (new Set(array)).size !== array.length;
}

If you only need string values in the array, the following will work:

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

We use a "hash table" valuesSoFar whose keys are the values we've seen in the array so far. We do a lookup using in to see if that value has been spotted already; if so, we bail out of the loop and return true.


If you need a function that works for more than just string values, the following will work, but isn't as performant; it's O(n2) instead of 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;
}

The difference is simply that we use an array instead of a hash table for valuesSoFar, since JavaScript "hash tables" (i.e. objects) only have string keys. This means we lose the O(1) lookup time of in, instead getting an O(n) lookup time of indexOf.

Domenic
  • 110,262
  • 41
  • 219
  • 271
  • 3
    About the first example you gave. Isn't the validation exactly the other way around? If your function is named `hasDuplicates`, then it should check if the set's size actually shrunk during the process of casting it, right? Therefore the boolean operator should be `!==` and not `===` – Tim Daubenschütz Jul 01 '15 at 13:45
  • pls edit. I can't edit as I'm not changing more than 6 characters. – Tim Daubenschütz Jul 03 '15 at 09:32
  • 1
    According to [MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Set) IE11 does not the support the constructor used in the first example – adam77 Feb 01 '16 at 19:40
  • 1
    Normal JS version returns `true` for the following array: `[1, '1']` – Kunal Jan 28 '18 at 06:31
  • Thus "if you only need string values in the array" preceding the answer. – Domenic Feb 15 '18 at 05:03
  • However it is not supported in IE11 as you mentioned.It would return size 0 .Try this in IE 11 `new Set([1, 2, 3, 4, 5])` – Sunil Hari May 31 '18 at 07:56
  • Solution 1 will not work for JSON objects check https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#ExamplesSection – iAviator Aug 08 '19 at 05:33
  • 1
    Hi! Just wanted to contribute with another solution that I ended up using. Just in case is useful for somebody: `[1,2,3,4,4].filter( (v, i, arr) => i !== arr.indexOf(v) )`. It will return an array with the repeated values (except the 1st occurrence). – Davo Jan 13 '20 at 19:34
  • ES2015 is a god. – Amir Hassan Azimi Feb 04 '20 at 23:27
18

You could use SET to remove duplicates and compare, If you copy the array into a set it will remove any duplicates. Then simply compare the length of the array to the size of the set.

function hasDuplicates(a) {

  const noDups = new Set(a);

  return a.length !== noDups.size;
}
Andor
  • 358
  • 3
  • 11
Helogale
  • 231
  • 2
  • 9
17

One line solutions with 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
Kordrad
  • 1,154
  • 7
  • 18
  • 3
    **FYI** - [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size) has a `.size` property, so you don't have to spread into an array to get `.length` – KyleMit Jan 22 '22 at 13:01
  • 1
    Ty, I changed it – Kordrad Jun 23 '23 at 07:34
6

Another approach (also for object/array elements within the array1) could be2:

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

See also...

1 needs a browser that supports JSON, or a JSON library if not.
2 edit: function can now be used for simple check or to return an array of duplicate values

KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • 3
    Non-showstopper issues worth being aware of: 1) mutates the original array to be sorted; 2) does not differentiate between `null`, `NaN`, `Infinity`, `+Infinity`, and `-Infinity`; 3) objects are considered equal if they have the same own-properties, even if they have different prototypes. – Domenic Sep 11 '11 at 06:40
  • 1
    @Domenic: yep, should've mentioned it. Edited to circumvent mutation of original array. – KooiInc Sep 11 '11 at 06:45
  • @Domenic: corrected for null/NaN/[+/-]Infinity, see edits. – KooiInc Sep 11 '11 at 06:53
  • @Domenic: Issue 3) is actually not a problem for me, because it is exactly what I want. I don't care about the prototype, just the values. – awe Nov 19 '15 at 05:59
3

You can take benefit of indexOf and lastIndexOf. if both indexes are not same, you have duplicate.

function containsDuplicates(a) {
  for (let i = 0; i < a.length; i++) {
    if (a.indexOf(a[i]) !== a.lastIndexOf(a[i])) {
      return true
    }
  }
  return false
}
Baqer Naqvi
  • 6,011
  • 3
  • 50
  • 68
3

If you are dealing with simple values, you can use array.some() and indexOf()

for example let's say vals is ["b", "a", "a", "c"]

const allUnique = !vals.some((v, i) => vals.indexOf(v) < i);

some() will return true if any expression returns true. Here we'll iterate values (from the index 0) and call the indexOf() that will return the index of the first occurrence of given item (or -1 if not in the array). If its id is smaller that the current one, there must be at least one same value before it. thus iteration 3 will return true as "a" (at index 2) is first found at index 1.

O-9
  • 1,626
  • 16
  • 15
2

is just simple, you can use the Array.prototype.every function

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;
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
alguerocode
  • 112
  • 4
2

Why use this method:

I think this is the best way to do it when dealing with multiple arrays and loops, this exaple is very simple but in some cases such when iterating with several loops and iterating through objects this is the most reliable and optimal way to do it.

Explanation:

In this example the array is iterated, element is the same as array[i] i being the position of the array that the loop is currently on, then the function checks the position in the read array which is initialized as empty, if the element is not in the read array it'll return -1 and it'll be pushed to the read array, else it'll return its position and won't be pushed, once all the element of array has been iterated the read array will be printed to console

let array = [1, 2, 3, 4, 5, 1, 2, 3, 5]
let read = []

array.forEach(element => {
  if (read.indexOf(element) == -1) {
    read.push(element)
    console.log("This is the first time" + element + " appears in the array")
  } else {
    console.log(element + " is already in the array")
  }
})

console.log(read)
1

One nice thing about solutions that use Set is O(1) performance on looking up existing items in a list, rather than having to loop back over it.

One nice thing about solutions that use Some is short-circuiting when the duplicate is found early, so you don't have to continue evaluating the rest of the array when the condition is already met.

One solution that combines both is to incrementally build a set, early terminate if the current element exists in the set, otherwise add it and move on to the next element.

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

According to JSBench.me, should preform pretty well for the varried use cases. The set size approach is fastest with no dupes, and checking some + indexOf is fatest with a very early dupe, but this solution performs well in both scenarios, making it a good all-around implementation.

KyleMit
  • 30,350
  • 66
  • 462
  • 664
0
    this.selectedExam = [];
    // example exam obj: {examId:1, name:'ExamName'}
    onExamSelect(exam: any) {
    if(!this.selectedExam.includes(exam?.name)){ 
      this.selectedExam.push(exam?.name);
    }}

In the above code, I have taken an array and on triggering a particular function (onExamSelect) we are checking duplicates and pushing unique elements.

-4
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;
}
progNewbie
  • 4,362
  • 9
  • 48
  • 107
  • 1
    Welcome to Stackoverflow. It would be great if you'd explain your answer instead of only posting some code. Thanks! – progNewbie Apr 27 '21 at 15:59