In short: keep the value if the position of the first occurrence of the element (indexOf
) is also the last position of the element in the array (lastIndexOf
).
If the indexes are not equal then the value is duplicated and you can discard it.
const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi',
'Pele', 'Messi', 'Van Basten', 'Baggio',
'Messi', 'Seedorf', 'Maradona'];
const uniqueArray = a.filter(function(item) {
return a.lastIndexOf(item) == a.indexOf(item);
});
console.log(uniqueArray);
/* output: ["Ronaldo", "Van Basten", "Baggio", "Seedorf"] */
Another idea is to perform an array iteration, add the values as the keys of an object, count the occurrences and then keep the keys with a total of occurrences equal to 1.
const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi',
'Pele', 'Messi', 'Van Basten', 'Baggio',
'Messi', 'Seedorf', 'Maradona'];
const obj = {};
const uniqueArray = [];
a.forEach((item) => {
obj[item] = (typeof obj[item] === 'undefined')? 1 : ++obj[item];
});
for (let key in obj) {
if (obj[key] === 1) {
uniqueArray.push(key)
}
}
console.log(uniqueArray);
/* output: ["Ronaldo", "Van Basten", "Baggio", "Seedorf"] */
The complexity of this code is linear while the first solution is quadratic.
I made a benchmark on JSPerf and the last approach is ~11x
times faster using an array of 535
items with 119
unique values.