8
var arr = ['test0','test2','test0'];

Like the above,there are two identical entries with value "test0",how to check it most efficiently?

4
  • 1
    What criteria of efficiency? Speed? Code readability? Memory usage? Commented Oct 14, 2009 at 7:14
  • do you wanna a remove it ? or just to find it ? Commented Oct 14, 2009 at 7:17
  • 1
    Ummm... why was this question edited instead of posted as a new one? I'm reverting to the original, since now the answers make no sense. Commented Oct 14, 2009 at 7:30
  • 1
    Mask: post a new question, instead of changing this one to a completely different question. Commented Oct 14, 2009 at 7:41

9 Answers 9

16

If you sort the array, the duplicates are next to each other so that they are easy to find:

arr.sort();
var last = arr[0];
for (var i=1; i<arr.length; i++) {
   if (arr[i] == last) alert('Duplicate : '+last);
   last = arr[i];
}
Sign up to request clarification or add additional context in comments.

4 Comments

... assuming your values are all strings or numbers. Sorting will do no good for an arbitrary array of objects.
If it's an arbitrary array of objects then it's also difficult to check if they're identical.
@Tim: Good point. However, if the can't be sorted, they can hardly be compared to look for duplicates...
You can check whether any array values are identical using the identity operator (===). Sorting an array of objects to bring duplicates to the start requires knowledge of the types of objects being compared in order to decide how to compare them.
6

This will do the job on any array and is probably about as optimized as possible for handling the general case (finding a duplicate in any possible array). For more specific cases (e.g. arrays containing only strings) you could do better than this.

function hasDuplicate(arr) {
    var i = arr.length, j, val;

    while (i--) {
        val = arr[i];
        j = i;
        while (j--) {
            if (arr[j] === val) {
                return true;
            }
        }
    }
    return false;
}

Comments

6

There are lots of answers here but not all of them "feel" nice... So I'll throw my hat in.

If you are using lodash:

function containsDuplicates(array) {
  return _.uniq(array).length !== array.length; 
}

If you can use ES6 Sets, it simply becomes:

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

With vanilla javascript:

function containsDuplicates(array) {
  return array
    .sort()
    .some(function (item, i, items) {
      return item === items[i + 1]
    })
}

However, sometimes you may want to check if the items are duplicated on a certain field.

This is how I'd handle that:

containsDuplicates([{country: 'AU'}, {country: 'UK'}, {country: 'AU'}], 'country')

function containsDuplicates(array, attribute) {
  return array
    .map(function (item) { return item[attribute] })
    .sort()
    .some(function (item, i, items) {
      return item === items[i + 1]
    })
}

2 Comments

Small Typo. Instead of new Set(array).length it should be new Set(array).size. So function will be containsDuplicates(array) { return array.length === new Set(array).size }
Have you performed perfomance testing on your solutions? They are in no means "fastest", especially the one using sort and some.
3

Loop stops when found first duplicate:

function has_duplicates(arr) {

    var x = {}, len = arr.length;
    for (var i = 0; i < len; i++) {
        if (x[arr[i]]) {
             return true;
        }
        x[arr[i]] = true;
    }
    return false;

}

Edit (fix 'toString' issue):

function has_duplicates(arr) {

    var x = {}, len = arr.length;
    for (var i = 0; i < len; i++) {
        if (x[arr[i]] === true) {
             return true;
        }
        x[arr[i]] = true;
    }
    return false;

}

this will correct for case has_duplicates(['toString']); etc..

4 Comments

Careful: using Object as a map has difficulties. Keys may only be strings, and names that are members of Object will confuse it. eg. has_duplicates(['toString']) is true.
As bobince says. All keys will be converted to strings. So the above would give a false positive with the following: [ {a: 1}, {b: 2} ] since both members of the array will become "[object Object]" when being stored as keys in x.
Gah, I hate SO on this. I downvoted and commented on your original answer and now cannot remove it.
In original question array contains only strings. You are correct -- my solition is not working for all possible types, but there is other task.
1

Sorting is O(n log n) and not O(n). Building a hash map is O(n). It costs more memory than an in-place sort but you asked for the "fastest." (I'm positive this can be optimized but it is optimal up to a constant factor.)

function hasDuplicate(arr) {
  var hash = {};
  var hasDuplicate = false;
   arr.forEach(function(val) {
     if (hash[val]) {
       hasDuplicate = true;
       return;
     }
     hash[val] = true;
  });
  return hasDuplicate;
}

Comments

1
    var index = myArray.indexOf(strElement);
    if (index < 0) {
        myArray.push(strElement);
        console.log("Added Into Array" + strElement);
    } else {
        console.log("Already Exists at " + index);
    }

1 Comment

You shall add the details to why and how is your method faster for a brief explanation.
1

You can convert the array to to a Set instance, then convert to an array and check if the length is same before and after the conversion.

const hasDuplicates = (array) => {
  const arr = ['test0','test2','test0'];
  const uniqueItems = new Set(array);
  
  return array.length !== uniqueItems.size();
};

console.log(`Has duplicates : ${hasDuplicates(['test0','test2','test0'])}`);
console.log(`Has duplicates : ${hasDuplicates(['test0','test2','test3'])}`);

2 Comments

Set has a size property, you don't need convert it back to array.
Thats a good point.
0

It depends on the input array size. I've done some performance tests with Node.js performance hooks and found out that for really small arrays (1,000 to 10,000 entries) Set solution might be faster. But if your array is bigger (like 100,000 elements) plain Object (i. e. hash) solution becomes faster. Here's the code so you can try it out for yourself:

const { performance } = require('perf_hooks');

function objectSolution(nums) {
  let testObj = {};
  for (var i = 0; i < nums.length; i++) {
    let aNum = nums[i];
    if (testObj[aNum]) {
      return true;
    } else {
      testObj[aNum] = true;
    }
  }

  return false;
}

function setSolution(nums) {
  let testSet = new Set(nums);
  return testSet.size !== nums.length;
}

function sortSomeSolution(nums) {
  return nums
    .sort()
    .some(function (item, i, items) {
      return item === items[i + 1]
    })
}

function runTest(testFunction, testArray) {
  console.log('   Running test:', testFunction.name);
  let start = performance.now();
  let result = testFunction(testArray);
  let end = performance.now();
  console.log('      Duration:', end - start, 'ms');
}

let arr = [];
let setSize = 100000;
for (var i = 0; i < setSize; i++) {
  arr.push(i);
}

console.log('Set size:', setSize);
runTest(objectSolution, arr);
runTest(setSolution, arr);
runTest(sortSomeSolution, arr);

On my Lenovo IdeaPad with i3-8130U Node.js v. 16.6.2 gives me following results for the array of 1,000:

timings for an array of 1,000 elements

results for the array of 100,000:

timings for an array of 100,000 elements

Comments

-1

Assuming all you want is to detect how many duplicates of 'test0' are in the array. I guess an easy way to do that is to use the join method to transform the array in a string, and then use the match method.

var arr= ['test0','test2','test0'];
var str = arr.join();

console.log(str) //"test0,test2,test0"

var duplicates = str.match(/test0/g);
var duplicateNumber = duplicates.length;

console.log(duplicateNumber); //2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.