I have an array of numbers that I need to make sure are unique. I found the code snippet below on the internet and it works great until the array has a zero in it. I found this other script here on SO that looks almost exactly like it, but it doesn't fail.
So for the sake of helping me learn, can someone help me determine where the prototype script is going wrong?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
If anyone using knockoutjs
BTW have look at all
ko.utils.array*
utilities.Many of the answers here may not be useful to beginners. If de-duping an array is difficult, will they really know about the prototype chain, or even jQuery?
In modern browsers, a clean and simple solution is to store data in a Set, which is designed to be a list of unique values.
The
Array.from
is useful to convert the Set back to an Array so that you have easy access to all of the awesome methods (features) that arrays have. There are also other ways of doing the same thing. But you may not needArray.from
at all, as Sets have plenty of useful features like forEach.If you need to support old Internet Explorer, and thus cannot use Set, then a simple technique is to copy items over to a new array while checking beforehand if they are already in the new array.
To make this instantly reusable, let's put it in a function.
So to get rid of the duplicates, we would now do this.
The
deduplicate(cars)
part becomes the thing we named result when the function completes.Just pass it the name of any array you like.
With JavaScript 1.6 / ECMAScript 5 you can use the native
filter
method of an Array in the following way to get an array with unique values:The native method
filter
will loop through the array and leave only those entries that pass the given callback functiononlyUnique
.onlyUnique
checks, if the given value is the first occurring. If not, it must be a duplicate and will not be copied.This solution works without any extra library like jQuery or prototype.js.
It works for arrays with mixed value types too.
For old Browsers (<ie9), that do not support the native methods
filter
andindexOf
you can find work arounds in the MDN documentation for filter and indexOf.If you want to keep the last occurrence of a value, simple replace
indexOf
bylastIndexOf
.With ES6 it could be shorten to this:
Thanks to Camilo Martin for hint in comment.
ES6 has a native object
Set
to store unique values. To get an array with unique values you could do now this:The constructor of
Set
takes an iterable object, like Array, and the spread operator...
transform the set back into an Array. Thanks to Lukas Liese for hint in comment.If you're using Prototype framework there is no need to do 'for' loops, you can use http://www.prototypejs.org/api/array/uniq like this:
Which will produce a duplicate array with no duplicates. I came across your question searching a method to count distinct array records so after
I used
and there was my simple result. p.s. Sorry if i misstyped something
edit: if you want to escape undefined records you may want to add
before, like this:
PERFORMANCE ONLY! this code is probably 10X faster than all the codes in here *works on all browsers and also has the lowest memory impact.... and more
if you don't need to reuse the old array;btw do the necessary other operations before you convert it to unique here is probably the fastest way to do this, also very short.
then you can try this
I came up with this function reading this article...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
I don't like the for loop. it has to many parameters.i like the while-- loop. while is the fastest loop in all browsers except the one we all like so much... chrome.
anyway i wrote the first function that uses while.And yep it's a little faster than the function found in the article.but not enough.
unique2()
next step use modern js.
Object.keys
i replaced the other for loop with js1.7's Object.keys... a little faster and shorter (in chrome 2x faster) ;). Not enough!.unique3()
.at this point i was thinking about what i really need in MY unique function. i don't need the old array, i want a fast function. so i used 2 while loops + splice.
unique4()
Useless to say that i was impressed.
chrome: the usual 150,000 operations per second jumped to 1,800,000 operations per second.
ie: 80,000 op/s vs 3,500,000 op/s
ios: 18,000 op/s vs 170,000 op/s
safari: 80,000 op/s vs 6,000,000 op/s
Proof http://jsperf.com/wgu or better use console.time... microtime... whatever
unique5()
is just to show you what happens if you want to keep the old array.Don't use
Array.prototype
if yu don't know what your doing. i just did alot of copy and past. UseObject.defineProperty(Array.prototype,...,writable:false,enumerable:false})
if you want to create a native prototype.example: https://stackoverflow.com/a/20463021/2450730Demo http://jsfiddle.net/46S7g/
NOTE: your old array is destroyed/becomestheunique after this operation.
if you can't read the code above ask, read a javascript book or here are some explainations about shorter code. https://stackoverflow.com/a/21353032/2450730
some are using
indexOf
... don't ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfhfor empty arrays
strange this hasn't been suggested before.. to remove duplicates by object key (
id
below) in an array you can do something like this: