How to create a list of unique items in JavaScript?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



How to create a list of unique items in JavaScript?



In my CouchDB reduce function I need to reduce a list of items to the unique ones.



Note: In that case it's ok to have a list, it will be a small number of items of string type.



My current way is to set keys of a object, then return the keys of that object
since the place the code can't use things like _.uniq for example.


_.uniq



I'd like to find a more elegant way to spell it than this.


function(keys, values, rereduce)
// values is a Array of Arrays
values = Array.concat.apply(null, values);
var uniq = ;
values.forEach(function(item) uniq[item] = true; );
return Object.keys(uniq);





depending on what you define as being elegant, you could lookup the source of underscore's unique on github
– Geert-Jan
Jul 27 '12 at 15:35





underscore is more expensive for string only and less elegant due to needing to work in the general case
– Ronny
Jul 27 '12 at 22:34





Do you need a reduce function? If you only need the unique values you can use the group=true option when requesting the view. For more info on that see CouchDB Wiki
– dignifiedquire
Jul 31 '12 at 19:20


group=true





a map view cannot use group
– Ronny
Jul 31 '12 at 20:48





Possible duplicate of [Get all unique values in an array (remove duplicates) stackoverflow.com/questions/1960473/…
– Gernot Krost
Nov 18 '17 at 20:44





6 Answers
6



Commonly, the approach you used is a good idea.
But I could propose a solution that will make the algorithm a lot faster.


function unique(arr)
var u = , a = ;
for(var i = 0, l = arr.length; i < l; ++i)
if(!u.hasOwnProperty(arr[i]))
a.push(arr[i]);
u[arr[i]] = 1;


return a;



As you can see we have only one loop here.



I've made an example that is testing both your and my solutions. Try to play with it.





i hoped for more pretty, but the speedup is quite something
– Ronny
Aug 23 '12 at 18:47





The speed of algorithm is always important when you have a deal with collections and loops.
– Eugene Naydenov
Aug 24 '12 at 7:09





If I were to use for(var i=0; i<arr.length; ++i) would it recount the array's length on every loop? Or why create a separate l variable?
– Markus Meskanen
Dec 15 '16 at 7:57


for(var i=0; i<arr.length; ++i)


l





@MarkusMeskanen It depends on the particular JavaScript engine implementation. Also, don't forget about the property lookup time.
– Eugene Naydenov
Dec 15 '16 at 11:35





FYI neither solution works with objects. e.g. unique([, a:1]) === [] — this is because you can only use strings as object keys. Likewise: unique(['1', 1]) === ['1']
– bfred.it
Feb 26 '17 at 6:40



unique([, a:1]) === []


unique(['1', 1]) === ['1']



An alternative that's suitable for small lists would be to ape the Unix command line approach of sort | uniq:


sort | uniq


function unique(a)
return a.sort().filter(function(value, index, array)
return (index === 0) );



This function sorts the argument, and then filters the result to omit any items that are equal to their predecessor.



The keys-based approach is fine, and will have better performance characteristics for large numbers of items (O(n) for inserting n items into a hashtable, compared to O(n log n) for sorting the array). However, this is unlikely to be noticeable on small lists. Moreover, with this version you could modify it to use a different sorting or equality function if necessary; with hash keys you're stuck with JavaScripts notion of key equality.





Beautiful, was able to use this in ember.js to filter a recordarray with Arrayproxy's "filter" function
– Epirocks
Mar 21 at 15:19




This is an old question, I know. However, it is at the top of some google searches, so I wanted to add that you can combine the answers from @RobHague and @EugeneNaydenov using the following:


function unique(arr)
let u = ;
return arr.filter((v) =>
return u[v] = !u.hasOwnProperty(v);
);
;



You can also ignore undefined values (often handy) by adding:


function unique(arr)
let u = ;
return arr.filter((v) =>
return u[v] = (v !== undefined && !u.hasOwnProperty(v));
);
;



You can play with this solution here: https://jsfiddle.net/s8d14v5n/



Using Object.keys will give you strings if you put in integer arguments (uniq([1,2,3]) => ['1','2','3']. Here's one with Array.reduce:


function uniq(list)
return list.reduce((acc, d) => acc.includes(d) ? acc : acc.concat(d), );



This should work with anything, not just strings:


export const getUniqueList = (a: Array<any>) : Array<any> =>

const set = new Set<any>();

for(let i = 0; i < a.length; i++)
if(!set.has(a[i]))
set.add(a[i]);



return Array.from(set.values());

;



what about


function unique(list)
for (i = 0; i<list.length; i++)
for (j=i+1; j<list.length; j++)
if (list[i] == list[j])
list.splice(j, 1);








You need to decrement j after running list.splice(). This kind of O(N^2) solution will work on small arrays, but I wouldn't use it once the arrays get bigger.
– sffc
Jul 27 '16 at 19:35






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard