Remove All Elements That Occur More Than Once From Array
Solution 1:
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', 'Jair', 'Baggio', 'Messi',
'Seedorf'];
const uniqueArray = a.filter(function(item) {
return a.lastIndexOf(item) == a.indexOf(item);
});
console.log(uniqueArray);
/* output: ["Ronaldo", "Maradona", "Jair", "Baggio", "Seedorf"] */
Solution 2:
You can count the item in each iteration so that you can include that in the condition:
const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];
const uniqueArray = a.filter(function(item, pos) {
var c = a.filter(i => i==item).length;
return a.indexOf(item) == pos && c <= 1;
})
console.log(uniqueArray);
Though the better solution would be to compare the index of the current array item with Array.prototype.indexOf() and Array.prototype.lastIndexOf():
const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];
const uniqueArray = a.filter(function(item, pos) {
return a.indexOf(item) === a.lastIndexOf(item);
})
console.log(uniqueArray);
Solution 3:
You can utilise a Map
to count how many times each entry shows up and then only take the ones that only do so once.
const a = ['Ronaldo', 'Pele', 'Maradona', 'Messi', 'Pele'];
const uniqueArray = onlyUniqueItems(a);
console.log(uniqueArray)
functiononlyUniqueItems(array) {
const map = newMap();
const result = [];
array.forEach(item => {
let amount = map.get(item) || 0;
map.set(item, ++amount); //pre-increment and then set the amount
});
map.forEach((amount, item) => {
if (amount == 1) {
result.push(item);
}
});
return result;
}
This will run in O(2n) as you will have to do two scans at most. You can achieve a similar result using a plain object and set key-values on it but a Map has the advantage of preserving the type of the items you had, whereas a plain object will convert all keys to strings:
const a = [1, 2, 3, 3, "4", "4", "5"];
const uniqueArray = onlyUniqueItems(a);
const uniqueArrayUsingObject = onlyUniqueItemsUsingObject(a);
console.log(uniqueArray)
console.log(uniqueArrayUsingObject)
functiononlyUniqueItems(array) {
const map = newMap();
const result = [];
//count occurences
array.forEach(item => {
let amount = map.get(item) || 0;
map.set(item, ++amount); //pre-increment and then set the amount
});
//extract only the items that show once
map.forEach((amount, item) => {
if (amount == 1) {
result.push(item);
}
});
return result;
}
functiononlyUniqueItemsUsingObject(array) {
const map = {};
const result = [];
//count occurences
array.forEach(item => {
let amount = map[item] || 0;
map[item] = ++amount; //pre-increment and then set the amount
});
//extract only the items that show onceObject.entries(map).forEach(([item, amount]) => {
if (amount == 1) {
result.push(item);
}
});
return result;
}
Solution 4:
The naive way would be to check for more than one occurence:
a.filter((el, i) => !(a.indexOf(el) !== i || a.indexOf(el, i) > -1)));
Or a more complicated one with multiple Sets (but O(n)):
const found = newSet, values = newSet;
for(const el of a)
if(!found.has(el)) {
found.add(el);
values.add(el);
} elseif(values.has(el) {
values.delete(el);
}
}
const result = [...values.values()];
Solution 5:
Why not to use Set
?
const theSet = newSet(a);
const values = set.values();
const uniqueArray = Array.from(values);
Post a Comment for "Remove All Elements That Occur More Than Once From Array"