How can i use Set() in objects? I read the documentation, it works with values in array, but with objects it do not work. Why? I want to avoid duplicate items that has exacly the same values.
let nameList_one = [{ name: 'harry', id: 1 }, { name: 'john', id: 2 }, { 'name': 'trevor', id: 3 }]
let nameList_two = [{ name: 'harry', id: 1 }, { name: 'ron', id: 4 }, { name: 'jackson', id: 5 }]
let fullNameList = [...nameList_one , ...nameList_two ]
let filteredList = [...new Set(fullNameList)] // the output is the merge of two array, duplicating "harry".
Output:
[{ name: 'harry', id: 1 }, { name: 'john', id: 2 }, { 'name': 'trevor', id: 3 }, { name: 'harry', id: 1 }, { name: 'ron', id: 4 }, { name: 'jackson', id: 5 }]
Expected Output:
[{ name: 'harry', id: 1 }, { name: 'john', id: 2 }, { 'name': 'trevor', id: 3 }, { name: 'ron', id: 4 }, { name: 'jackson', id: 5 }]
Thanks!!
Relevant info: How to customize object equality for Javascript Set - spoiler: "you can't" so you can't really use a Set for what you're trying to do. It simply doesn't do what you're looking for and can't be customized to do it either.
An Array of Objects is created using the Object class, and we know Object class is the root class of all Classes. We use the Class_Name followed by a square bracket [] then object reference name to create an Array of Objects.
Sets are supposed to contain unique objects, but it doesn't work for objects in javascript.
This doesn't work with objects because they are not same objects:
{ name: 'harry', id: 1 } !== { name: 'harry', id: 1 }
A way that may work is:
let filteredList = [...new Set(fullNameList.map(JSON.stringify))].map(JSON.parse);
It cannot be recommended, because it uses serialization where it's unnecessary. Serialization will destroy object instances that cannot be serialized, will ignore non-enumerable properties and won't handle circular references. Objects that have different property order won't be removed as duplicates. Their properties should be sorted first. In case there are nested objects, keys should be sorted recursively. This makes this approach impractical.
If the objects are identified by one or several fields, Map
with serialized fields as map keys can be used:
let filteredList = [
...new Map(fullNameList.map(obj => [`${obj.id}:${obj.name}`, obj]))
.values()
];
A nice way of doing this is to subclass Set
.
class UniqueNameSet extends Set {
constructor(values) {
super(values);
const names = [];
for (let value of this) {
if (names.includes(value.name)) {
this.delete(value);
} else {
names.push(value.name);
}
}
}
}
This gives you all the other methods/properties of Set
, but adds the extra functionality you are looking for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With