This seems like such a simple need but I've spent an inordinate amount of time trying to do this to no avail. I've looked at other questions on SO and I haven't found what I need. I have a very simple JavaScript array such as peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");
that may or may not contain duplicates and I need to simply remove the duplicates and put the unique values in a new array. That's it. I could point to all the codes that I've tried but I think it's useless because they don't work. If anyone has done this and can help me out I'd really appreciate it. JavaScript or jQuery solutions are both acceptable.
|
||||
Quick and dirty using jQuery:
|
|||
|
"Smart" but naïve way
Basically, we iterate over the array and, for each element, check if the first position of this element in the array is equal to the current position. Obviously, these two positions are different for duplicate elements. Using the 3rd ("this array") parameter of the filter callback we can avoid a closure of the array variable:
Although concise, this algorithm is not particularly efficient for large arrays (quadratic time). Hashtables to the rescue
This is how it's usually done. The idea is to place each element in a hashtable and then check for its presence instantly. This gives us linear time, but has at least two drawbacks:
That said, if your arrays contain only primitives and you don't care about types (e.g. it's always numbers), this solution is optimal. The best from two worldsAn universal solution combines both approaches: it uses hash lookups for primitives and linear search for objects.
sort | uniqAnother option is to sort the array first, and then remove each element equal to the preceding one:
Again, this doesn't work with objects (because all objects are equal for Unique by...Sometimes it's desired to uniquify a list based on some criteria other than just equality, for example, to filter out objects that are different, but share some property. This can be done elegantly by passing a callback. This "key" callback is applied to each element, and elements with equal "keys" are removed. Since
A particularly useful
LibrariesBoth underscore and Lo-Dash provide
This is quadratic, but there are nice additional goodies, like wrapping native If you're using jQuery and can't stand anything without a dollar before it, it goes like this:
which is, again, a variation of the first snippet. PerformanceFunction calls are expensive in Javascript, therefore the above solutions, as concise as they are, are not particularly efficient. For maximal performance, replace
This chunk of ugly code does the same as the snippet #3 above, but an order of magnitude faster:
ES6ES6 provides the Set object, which makes things a whole lot easier:
Note that, unlike in python, ES6 sets are iterated in insertion order, so this code preserves the order of the original array. However, if you need an array with unique elements, why not use sets right from the beginning? |
|||||||||||||||||||||
|
Got tired of seeing all bad examples with for-loops or jQuery. Javascript has the perfect tools for this nowadays: sort, map and reduce. Uniq reduce while keeping existing order
Faster uniq with sortingThere are probably faster ways but this one is pretty decent.
Update 2015: ES6 version:In ES6 you have Sets and Spread which makes it very easy and performant to remove all duplicates:
Sort based on occurrence:Someone asked about ordering the results based on how many unique names there are:
|
|||||||||||||||||||||
|
Use Underscore.jsIt's a library with a host of functions for manipulating arrays.
Note: Lo-Dash (an underscore competitor) also offers a comparable .uniq implementation. |
|||||
|
Vanilla JS: Remove duplicates using an Object like a Set You can always try putting it into an object, and then iterating through its keys:
Vanilla JS: Remove duplicates by tracking already seen values (order safe) Or, for an order-safe version, use an object to store all previously seen values, and check values against it before before adding to an array.
Example usage:
|
|||||||||||||
|
A single line version using array filter and indexOf functions:
|
|||||||||||||||||
|
The most concise way to remove duplicates from an array using native javascript functions is to use a sequence like below:
there's no need for
Yet another ES6(2015) way of doing this that already works on a few browsers is:
or even using the spread operator:
cheers! |
|||||||||||||||||
|
Here is a simple answer to the question.
|
|||||||||
|
The following is more than 80% faster than the jQuery method listed (see tests below). It is an answer from a similar question a few years ago, if I come across the person who originally proposed it I will post credit. Pure JS.
My Test Case comparison: http://jsperf.com/remove-duplicate-array-tests |
|||||||||
|
The top answers have complexity of
This will work for strings, numbers, and dates. If your array contains complex objects (ie, they have to be compared with
|
|||||||||||||||||||||
|
You could also use the However, the code there isn’t very well written, since it declares the |
|||
|
In ECMAScript 6 (aka ECMAScript 2015),
|
|||||||||||||
|
Apart from being a simpler, more terse solution than the current answers (minus the future-looking ES6 ones), I perf tested this and it was much faster as well:
One caveat: Array.lastIndexOf() was added in IE9, so if you need to go lower than that, you'll need to look elsewhere. |
||||
|
|
||||
|
I had done a detailed comparison of dupes removal at some other question but having noticed that this is the real place i just wanted to share it here as well. I believe this is the best way to do this
OK .. even though this one is O(n) and the others are O(n^2) i was curious to see benchmark comparison between this reduce / look up table and filter/indexOf combo (I choose Jeetendras very nice implementation http://stackoverflow.com/a/37441144/4543207). I prepare a 100K item array filled with random positive integers in range 0-9999 and and it removes the duplicates. I repeat the test for 10 times and the average of the results show that they are no match in performance.
Well ok so far so good. But let's do it properly this time in the ES6 style. It looks so cool..! But as of now how it will perform against the powerful lut solution is a mystery to me. Lets first see the code and then benchmark it.
Wow that was short..! But how about the performance..? It's beautiful... Since the heavy weight of the filter / indexOf lifted over our shoulders now i can test an array 1M random items of positive integers in range 0..99999 to get an average from 10 consecutive tests. I can say this time it's a real match. See the result for yourself :)
Which one would you use..? Well not so fast...! Don't be deceived. Map is at displacement. Now look... in all of the above cases we fill an array of size n with numbers of range < n. I mean we have an array of size 100 and we fill with random numbers 0..9 so there are definite duplicates and "almost" definitely each number has a duplicate. How about if we fill the array in size 100 with random numbers 0..9999. Let's now see Map playing at home. This time an Array of 100K items but random number range is 0..100M. We will do 100 consecutive tests to average the results. OK let's see the bets..! <- no typo
Now this is the spectacular comeback of Map()..! May be now you can make a better decision when you want to remove the dupes. Well ok we are all happy now. But the lead role always comes last with some applause. I am sure some of you wonder what Set object would do. Now that since we are open to ES6 and we know Map is the winner of the previous games let us compare Map with Set as a final. A typical Real Madrid vs Barcelona game this time... or is it? Let's see who will win the el classico :)
Wow.. man..! Well unexpectedly it didn't turn out to be an el classico at all. More like Barcelona FC against CA Osasuna :)) |
|||
|
A slight modification of thg435's excellent answer to use a custom comparator:
|
|||
|
This is probably one of the fastest way to remove permanently the duplicates from an array 10x times faster than the most functions here.& 78x faster in safari
if you can't read the code above ask, read a javascript book or here are some explainations about shorter code. http://stackoverflow.com/a/21353032/2450730 |
|||||||||||||||||||||
|
Another method of doing this without writing much code is using the ES5
Extracted in a function
|
|||||||||
|
go for this one ,
Now uniqueArray contains no duplicates |
|||
|
Best method is using Underscore.js, it needs to do just one step. i.e _.uniq(list) . it will return list with uniq data. |
|||
|
If by any chance you were using
You could do
|
|||
|
Nested loop method for removing duplicates in array and preserving original order of elements.
Explanation: Inner loop compares first element of array with all other elements starting with element at highest index. Decrementing towards the first element a duplicate is spliced from the array. When inner loop is finished the outer loop increments to the next element for comparison and resets the new length of the array. |
|||
|
https://jsfiddle.net/2w0k5tz8/
Loop through, remove duplicates, and create a clone array place holder because the array index will not be updated. Loop backward for better performance ( your loop wont need to keep checking the length of your array) |
|||
|
|
|||
|
This was just another solution but different than the rest.
|
|||
|
Here is another approach using jQuery,
Author: William Skidmore |
|||
|
|
|||
|
If you don't want to include a whole library, you can use this one off to add a method that any array can use:
|
|||
|
If you're creating the array yourself, you can save yourself a loop and the extra unique filter by doing the check as you're inserting the data;
|
|||||
|
The easiest way to remove string duplicates is to use associative array and then iterate over the associative array to make the list/array back. Like below:
Voila, now duplicates are gone! |
||||
|
_.uniq(peoplenames)
solves this lodash.com/docs#uniq – Connor Leech Jul 29 '14 at 19:29