Problem
I’ve got a bunch of numbers that I need to make sure are all different. The code snippet below was found on the internet and works wonderfully until the array contains a zero. I discovered another script that seems pretty identical to it on Stack Overflow, but it doesn’t fail.
So, for the interest of learning, could someone point out 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;
}
Asked by Mottie
Solution #1
To get an array with unique values in JavaScript 1.6 / ECMAScript 5, utilize the native filter method of an Array like follows:
The native method filter will loop through the array and leave only those entries that pass the given callback function onlyUnique.
onlyUnique determines if the provided value is the first time it appears. If it doesn’t, it’s a duplicate that won’t be replicated.
This solution does not require any additional libraries, such as jQuery or prototype. js.
It also works with arrays of mixed value types.
In the MDN documentation for filter and indexOf, there are workarounds for ancient browsers (IE9) that don’t support the native methods filter and indexOf.
Simply replace indexOf with lastIndexOf if you want to maintain the last occurrence of a value.
This can be condensed using ES6 to:
Camilo Martin provided a helpful hint in a comment.
A native object Set in ES6 is used to hold unique data. You could now execute the following to get an array with unique values:
Set’s constructor takes an iterable object, such as an Array, and uses the spread operator… to convert it back to an Array. Lukas Liese provided a helpful hint in a remark.
Answered by TLindig
Solution #2
Answer for ES6/ES2015 has been updated: The single line solution is: Using the Set and spread operators (thanks to le-m), the single line solution is:
let uniqueItems = [...new Set(items)]
Which returns
[4, 5, 6, 3, 2, 23, 1]
Answered by A.T.
Solution #3
I divided all of the answers into four groups:
Here are a few examples of codes encountered in answers:
function uniqueArray1( ar ) {
var j = {};
ar.forEach( function(v) {
j[v+ '::' + typeof v] = v;
});
return Object.keys(j).map(function(v){
return j[v];
});
}
function uniqueArray2(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
a.push(arr[i]);
return a;
}
function uniqueArray3(a) {
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
// usage
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']
return unique;
}
function uniqueArray4(a) {
return [...new Set(a)];
}
And I was curious as to which was the faster. To test functionalities, I created a sample Google Sheet. I can’t test ECMA 6 because it isn’t available in Google Sheets.
The following is the outcome of the tests:
Because hash is used, I anticipated to see that code using object would win. So I’m delighted that Chrome and Internet Explorer produced the greatest results for this method. The code was provided by @rab.
ES6 Engine with Google Script support. Now I tested the previous code with Sets and found that it was faster than the object method.
Answered by Max Makhrov
Solution #4
Underscore.js is another option.
which will return:
[1, 2, 3, 4]
Answered by kornfridge
Solution #5
With ES6 syntax
(x, I a) => a.indexOf(x) == I list = list.filter((x, I a) => a.indexOf(x) == I
x --> item in array
i --> index of item
a --> array reference, (in this case "list")
With ES5 syntax
list = list.filter(function (x, i, a) {
return a.indexOf(x) == i;
});
Browser Compatibility: IE9+
Answered by Vamsi
Post is based on https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates