46

I wanted to write a javascript function which checks if array contains duplicate values or not.

I have written the following code but its giving answer as "true" always.

Can anybody please tell me what am I missing.

function checkIfArrayIsUnique(myArray) 
    {
        for (var i = 0; i < myArray.length; i++) 
        {
            for (var j = 0; j < myArray.length; j++) 
            {
                if (i != j) 
                {
                    if (myArray[i] == myArray[j]) 
                    {
                        return true; // means there are duplicate values
                    }
                }
            }
        }
        return false; // means there are no duplicate values.
    }
7
  • You're comparing the same index ( when i == j ). Of course they are the same. Commented Oct 29, 2013 at 10:47
  • 3
    What does that mean, "array is unique"? Commented Oct 29, 2013 at 10:47
  • 1
    You want to check if each of the values in the array are unique (check for duplicates) or if the array itself is unique compared to another array? Commented Oct 29, 2013 at 10:48
  • Edited the question to be more specific. Hope it clear the doubts. Commented Oct 29, 2013 at 10:49
  • 1
    You could also change the second loop to for (var j = i; j < myArray.length; j++) as you have already checked the earlier indexes for uniqueness so there is no need to compare them again. Commented Oct 29, 2013 at 10:53

17 Answers 17

123

An easy solution, if you've got ES6, uses Set:

function checkIfArrayIsUnique(myArray) {
  return myArray.length === new Set(myArray).size;
}

let uniqueArray = [1, 2, 3, 4, 5];
console.log(`${uniqueArray} is unique : ${checkIfArrayIsUnique(uniqueArray)}`);

let nonUniqueArray = [1, 1, 2, 3, 4, 5];
console.log(`${nonUniqueArray} is unique : ${checkIfArrayIsUnique(nonUniqueArray)}`);

Sign up to request clarification or add additional context in comments.

3 Comments

This does not work for an array of arrays: [['x','y'], ['a','b'], ['42', 'awerq'], ['12'], ['x', 'y']]
@J.E.C. Sure it does. The first and second ['x','y'] elements are different objects in memory.
@J.E.C. ...but if you want something that can handle array equality, I made an answer for that.
26
let arr = [11,22,11,22];

let hasDuplicate = arr.some((val, i) => arr.indexOf(val) !== i);
// hasDuplicate = true

True -> array has duplicates

False -> uniqe array

4 Comments

you could write as a one-liner (with some strict equality): a.some((val, i) => a.indexOf(val) !== i);
if you want the array without the duplicates: const filtered = a.filter((val, i) => a.indexOf(val) === i); NB: these only work for arrays of primitive values
If you use findIndex() instead of indexOf(), it will stop when it finds a match instead of continuing with the rest of the array.
@bobpal both findIndex() and indexOf() will stop after find the first value and will not continue till the rest of the array.
23

This should work with only one loop:

function checkIfArrayIsUnique(arr) {
    var map = {}, i, size;

    for (i = 0, size = arr.length; i < size; i++){
        if (map[arr[i]]){
            return false;
        }

        map[arr[i]] = true;
    }

    return true;
}

Comments

21

You got the return values the wrong way round:

  • As soon as you find two values that are equal, you can conclude that the array is not unique and return false.

  • At the very end, after you've checked all the pairs, you can return true.

If you do this a lot, and the arrays are large, you might want to investigate the possibility of sorting the array and then only comparing adjacent elements. This will have better asymptotic complexity than your current method.

3 Comments

Thanks for your answer. I think my function was correct but the return values were being send the wrong way.
Also I was passing null values in the array and hence I was getting wrong answer. Anyways, my problem is solved.
@NPE how will sorting way have "better asymptotic complexity"? it increases the time complexity to O(nlogn) from O(n). the way does drop the space complexity from O(n) to O(1). Were you talking about space complexity?
7

Assuming you're targeting browsers that aren't IE8,

this would work as well:

function checkIfArrayIsUnique(myArray) 
{
    for (var i = 0; i < myArray.length; i++) 
    {
        if (myArray.indexOf(myArray[i]) !== myArray.lastIndexOf(myArray[i])) { 
            return false; 
        } 
    } 
    return true;   // this means not unique
}

Comments

2

Here's an O(n) solution:

function hasDupes(arr) {
  /* temporary object */
  var uniqOb = {};
  /* create object attribute with name=value in array, this will not keep dupes*/
  for (var i in arr)
    uniqOb[arr[i]] = "";
  /* if object's attributes match array, then no dupes! */
  if (arr.length == Object.keys(uniqOb).length)
    alert('NO dupes');
  else
    alert('HAS dupes');


}
var arr = ["1/1/2016", "1/1/2016", "2/1/2016"];
hasDupes(arr);

https://jsfiddle.net/7kkgy1j3/

Comments

2

Another solution:

 Array.prototype.checkIfArrayIsUnique = function() {
    this.sort();    
    for ( var i = 1; i < this.length; i++ ){
        if(this[i-1] == this[i])
            return false;
    }
    return true;
    }

5 Comments

I'm not sure if this is the best solution, it's frowned upon to directly add onto a prototype of a native in javaScript, this should just be a regular function to prevent possible conflicts.
Note that this doesn't work if there are more than 2 duplicate values.
Why is this the best solution? You're adding to the prototype chain seemingly for no good reason and it is not as performant as the answers that do it within one loop (since you sort the array first). Perhaps explain why you think this is the best solution?
Sorting costs 0(n*log(n)) while you can tell whether duplicates exist in O(n) - Far from best solution.
Also, wouldn't sort mutate the array? That might be a big problem.
2
function hasNoDuplicates(arr) {
    return arr.every(num => arr.indexOf(num) === arr.lastIndexOf(num));
}

hasNoDuplicates accepts an array and returns true if there are no duplicate values. If there are any duplicates, the function returns false.

Comments

1

Without a for loop, only using Map().

You can also return the duplicates.

(function(a){
  let map = new Map();

  a.forEach(e => {
    if(map.has(e)) {
      let count = map.get(e);
      console.log(count)
      map.set(e, count + 1);
    } else {
      map.set(e, 1);
    }
  });

  let hasDup = false;
  let dups = [];
  map.forEach((value, key) => {
    if(value > 1) {
      hasDup = true;
      dups.push(key);
    }
  });
   console.log(dups);
   return hasDup;
 })([2,4,6,2,1,4]);

Comments

1

Late answer but can be helpful

function areThereDuplicates(args) {

    let count = {};
    for(let i = 0; i < args.length; i++){
         count[args[i]] = 1 + (count[args[i]] || 0);
    }
    let found = Object.keys(count).filter(function(key) {
        return count[key] > 1;
    });
    return found.length ? true : false; 
}

areThereDuplicates([1,2,5]);

Comments

1

If your array nests other arrays/objects, using the Set approach may not be what you want since comparing two objects compares their references. If you want to check that their contained values are equal, something else is needed. Here are a couple different approaches.

Approach 1: Map using JSON.stringify for keys

If you want to consider objects with the same contained values as equal, here's one simple way to do it using a Map object. It uses JSON.stringify to make a unique id for each element in the array.

I believe the runtime of this would be O(n * m) on arrays, assuming JSON.stringify serializes in linear time. n is the length of the outer array, m is size of the arrays. If the objects get very large, however, this may slow down since the keys will be very long. Not a very space-efficient implementation, but it is simple and works for many data types.

function checkArrayDupeFree(myArray, idFunc) {
    const dupeMap = new Map();
    for (const el of myArray) {
        const id = idFunc(el);
        if (dupeMap.has(id))
            return false;
        dupeMap.set(id, el);
    }
    return true;
}

const notUnique = [ [1, 2], [1, 3], [1, 2] ];
console.log(`${JSON.stringify(notUnique)} has no duplicates? ${checkArrayDupeFree(notUnique, JSON.stringify)}`);

const unique = [ [2, 1], [1, 3], [1, 2] ];
console.log(`${JSON.stringify(unique)} has no duplicates? ${checkArrayDupeFree(unique, JSON.stringify)}`);

Of course, you could also write your own id-generator function, though I'm not sure you can do much better than JSON.stringify.

Approach 2: Custom HashMap, Hashcode, and Equality implementations

If you have a lot of big arrays, it may be better performance-wise to implement your own hash/equality functions and use a Map as a HashMap.

In the following implementation, we hash the array. If there is a collision, map a key to an array of collided values, and check to see if any of the array values match according to the equality function.

The downside of this approach is that you may have to consider a wide range of types for which to make hashcode/equality functions, depending on what's in the array.

function checkArrayDupeFreeWHashes(myArray, hashFunc, eqFunc) {
    const hashMap = new Map();
    
    for (const el of myArray) {
        const hash = hashFunc(el);
        const hit = hashMap.get(hash);
    
        if (hit == null)
            hashMap.set(hash, [el]);
        else if (hit.some(v => eqFunc(v, el)))
            return false;
        else
            hit.push(el);
    }

    return true;
}

Here's a demo of the custom HashMap in action. I implemented a hashing function and an equality function for arrays of arrays.

function checkArrayDupeFreeWHashes(myArray, hashFunc, eqFunc) {
    const hashMap = new Map();
    
    for (const el of myArray) {
        const hash = hashFunc(el);
        const hit = hashMap.get(hash);
    
        if (hit == null)
            hashMap.set(hash, [el]);
        else if (hit.some(v => eqFunc(v, el)))
            return false;
        else
            hit.push(el);
    }

    return true;
}

function arrayHasher(arr) {
    let hash = 19;
    for (let i = 0; i < arr.length; i++) {
        const el = arr[i];
        const toHash = Array.isArray(el)
            ? arrayHasher(el)
            : el * 23;
        hash = hash * 31 + toHash;
    }

    return hash;
}

function arrayEq(a, b) {
    if (a.length != b.length)
        return false;

    for (let i = 0; i < a.length; i++) {
        if ((Array.isArray(a) || Array.isArray(b)) && !arrayEq(a[i], b[i]))
            return false;
        else if (a[i] !== b[i])
            return false;
    }

    return true;
}

const notUnique = [ [1, 2], [1, 3], [1, 2] ];
const unique = [ [2, 1], [1, 3], [1, 2] ];
console.log(`${JSON.stringify(notUnique)} has no duplicates? ${checkArrayDupeFreeWHashes(notUnique, arrayHasher, arrayEq)}`);
console.log(`${JSON.stringify(unique)} has no duplicates? ${checkArrayDupeFreeWHashes(unique, arrayHasher, arrayEq)}`);

Comments

0

The code given in the question can be better written as follows

function checkIfArrayIsUnique(myArray) 
    {
        for (var i = 0; i < myArray.length; i++) 
        {
            for (var j = i+1; j < myArray.length; j++) 
            {                  
                    if (myArray[i] == myArray[j]) 
                    {
                        return true; // means there are duplicate values
                    }

            }
        }
        return false; // means there are no duplicate values.
    }

1 Comment

This seems to only improve the performance of that function, without fixing the problem the asked has/had. I might be wrong, in this case, can you update your answer with more details about how your code addresses the problem?
0

Returns the duplicate item in array and creates a new array with no duplicates:

 var a = ["hello", "hi", "hi", "juice", "juice", "test"];
    var b = ["ding", "dong", "hi", "juice", "juice", "test"];
    var c = a.concat(b);
    var dupClearArr = [];

    function dupArray(arr) {

        for (i = 0; i < arr.length; i++) {
            if (arr.indexOf(arr[i]) != i && arr.indexOf(arr[i]) != -1) {
                console.log('duplicate item ' + arr[i]);
            } else {
                dupClearArr.push(arr[i])
            }

        }
        console.log('actual array \n' + arr + ' \nno duplicate items array \n' + dupClearArr)
    }

    dupArray(c);

Comments

0
const containsMatches = (a1, a2) => a1.some((v) => a2.includes(v));

3 Comments

I see a1 and a2. Which one is being checked for duplicates?
The ‘some’ method on a1 is being used to iterate over all the values, and checks if that value (v) is in a2.
Still, there's not clear how you can use the code to check for duplicates. Can you add a usage example?
-1
function checkIfArrayIsUnique(myArray) 
    {
      isUnique=true

        for (var i = 0; i < myArray.length; i++) 
        {
            for (var j = 0; j < myArray.length; j++) 
            {
                if (i != j) 
                {
                    if (myArray[i] == myArray[j]) 
                    {
                        isUnique=false
                    }
                }
            }
        }
        return isUnique;
    }

This assume that the array is unique at the start.

If find two equals values, then change to false

Comments

-1

i think this is the simple way

$(document).ready(function() {

  var arr = [1,2,3,9,6,5,6];
  
  console.log( "result =>"+ if_duplicate_value (arr));
  
});


function if_duplicate_value (arr){
    
    for(i=0;i<arr.length-1;i++){
        
        for(j=i+1;j<arr.length;j++){
            
            if(arr[i]==arr[j]){
                
                return true;
                
            }
            
        }
        
    }
    
    return false;
    
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Comments

-1

var c=[2,2,3,3,5,5,4,4,8,8];

for(var i=0; i<b.length; i++){
    for(var j=i+1; j<b.length; j++){
        if(c[i]==c[j]){
            console.log(c[j]);
        }
    }
}

1 Comment

Uncaught ReferenceError: b is not defined

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.