38

How can I use lodash utilities in order to check an array for duplicate values?

I want to input ['foo', 'foo', 'bar'] and have the function return true. And input ['foo', 'bar', 'baz'] and have the function return false.

1

6 Answers 6

69

You can use uniq to check:

function hasDuplicates(a) {
  return _.uniq(a).length !== a.length; 
}

var a = [1,2,1,3,4,5];
var b = [1,2,3,4,5,6];

document.write(hasDuplicates(a), ',',hasDuplicates(b));
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.1.0/lodash.min.js"></script>

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

Comments

24

As of ES6 you can simply use Set so this becomes:

let hasDuplicates = arr => new Set(arr).size != arr.length

console.log(hasDuplicates([5,3,2,1,2,1,2,1]))
console.log(hasDuplicates([1,2,3,4,5]))

Which somewhat negates the use of lodash in this particular case.

Comments

7

You could check that there is _.some element in the array which does not return its own location when looked up in the array. In other words, there is at least one element which has a match earlier in the array.

function hasDuplicates(array) {
    return _.some(array, function(elt, index) { 
        return array.indexOf(elt) !== index; 
    });
}

Perhaps this is faster than the _.uniq solution, since it will identify the first duplicated element right away without having to compute the entire unique-ified array.

Or, depending on your coding style and desire for readability, and if you want to use ES6 arrow functions for brevity:

var earlierMatch  = (elt, index, array) => array.indexOf(elt) !== index;
var hasDuplicates = array => _.some(array, earlierMatch);

2 Comments

Nit-pick: indexOf (O(n)) within a some (O(n)) -> O(n2).
Yeah, this is an O(n^2) algorithm for checking for duplicates. I wouldn't call that a nitpick, more of a major flaw.
3

Well, there's always. lodash's _.uniq() function. That function actually returns a new array that only contains unique values, so checking to see if the length of the array has changed would get you your 'true' or 'false' value to return yourself, I believe.

Comments

2

I don't know lodash but I submit:

_.any(_.countBy(['foo', 'foo', 'bar']), function(x){ return x > 1; });

The problem with all the solutions proposed so far is that the entire input array needs processing to get an answer, even if the answer is obvious from the first 2 elements of the array.

1 Comment

As of version 4 of lodash, _.any is deprecated in favor of _.some
0
const array = [1, 2, 1]
array.some((el, idx) => array.lastIndexOf(el) !== idx)
// true

1 Comment

This is O(n^2), but O(n) solution exists: stackoverflow.com/a/56317910

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.