well, there is no native ecmascript class like std::set, where you pass an comparator function. You can implement this data structure, of course, as in any other programming language. But for most use cases i suggest something easier:
- If your objects have some kind of key or id field, and you want O(1) operations for operations like find/add/update/delete, you should use a map using this id field.
- If you don't have a key, just want avoid duplications in a collection, you can use map or even set, using
JSON.stringify(o, Object.keys(o).sort())
as an id. If you have nested objects or arrays, you should short its items either (i didn't wrote that part).
I wrote a class that can match both:
class ObjectSet {
constructor(iterable) {
this.map = new Map()
if(!iterable) {
return;
}
for(o of iterable) {
this.map.set(this._getId(o), o);
}
}
_getId(o) {
return o.id ? o.id :
JSON.stringify(o, Object.keys(o).sort());
}
get(id) {
return this.map.get(id);
}
has(o) {
return this.map.has(this._getId(o));
}
//add or update. Call "add" if you want to match ES6 Set interface
set(o) {
this.map.set(this._getId(o), o);
}
delete(o) {
this.map.delete(this._getId(o));
}
values() {
return this.map.values();
}
[Symbol.iterator] () {
return this.values();
}
get size() {
return this.map.size;
}
}
//first use case example, fast find and update:
let objSet = new ObjectSet();
//add
objSet.set({
id: 1,
name: "John",
age: 30
});
const eric = {
id: 2,
name: "Eric",
age: 27
}
//add
objSet.set(eric)
console.log(objSet.size); //2
//update object of id 2
objSet.set({
id: 2,
name: "Eric",
age: 28
})
console.log(objSet.size); // still 2
for(o of objSet) {
console.log(o);
}
/*
prints:
{ id: 1, name: 'John Abbot', age: 30 }
{ id: 2, name: 'Eric', age: 28 }
*/
objSet.delete({id: 1});//deletes john
objSet.delete(eric);
console.log(objSet.size);//0
//second use case, lets remove duplicated objects using this class
let points = [
{
x: 10,
y: 40
},
{
x: 10,
y: 40
},
{
x: 10,
y: 35
}
]
//lets remove duplicated objects using ObjectSet:
objSet = new ObjectSet(points);
console.log(o.size);//2
for(o of objSet) {
console.log(o);
}
//same with set method
objSet.set({
x: 10,
y: 35
});
console.log(objSet.size);//still 2