I am very new to Javascript and wondering if it is possible to create a Set of user-defined objects in a way that allows me to specify the function that is used to make equality comparisons?
Here's a contrived example just to illustrate the functionality that I'm looking for:
myClass = function(val){
var self = this;
self.val = val
self.equals = //used defined equals function
}
a = new myClass(1.0)
b = new myClass(2.0)
c = new myClass(2.0)
s = new Set() //does not have to be actual "Set"
s.add(a)
s.add(b)
s.add(c)
s.size === 2 //returns true
s.has(a) //returns true
s.has(b) //returns true
s.has(c) //returns true
I've found Set implementations (like this one), but it seems like are only designed for values, not user-defined objects. I suspect that there are other implementations that use === but this would not be useful in my case since I don't believe that I can override === either.
My question is very similar to this question. I'm posting it again since: a) I don't necessarily need a native ES6 solution and would be open to using a third party library. and b) it's been some time since that question was posted.
If you would accept to work with/override valueOf, then you could proceed like this:
// Implementation of special Set:
function mySet() {
var self = this;
self.size = 0;
// Use a private map that will be keyed by the valueOf() of each added item:
var map = new Map();
self.add = function (item) {
map.set(item.valueOf(), item);
self.size = map.size;
};
self.has = function (item) {
return map.has(item.valueOf());
};
self[Symbol.iterator] = function* () {
for (var pair of map) {
yield pair[1]; // return the item ( not the valueOf() in [0])
}
};
// etc...
}
// Test code:
myClass = function(val){
var self = this;
self.val = val;
self.valueOf = function () { return self.val; };
}
a = new myClass(1.0);
b = new myClass(2.0);
c = new myClass(2.0);
s = new mySet(); //does not have to be actual "Set"
s.add(a);
s.add(b);
s.add(c);
document.write('size: ' + s.size + '<br>');
document.write('has(a): ' + s.has(a) + '<br>');
document.write('has(b): ' + s.has(b) + '<br>');
document.write('has(c): ' + s.has(c) + '<br>');
for (item of s) {
document.write('stored item: ' + JSON.stringify(item) + '<br>');
};
Months later, I answered a similar question, where I did not suggest the use of valueOf, but a function that could be provided to the MySet constructor, defaulting to JSON.stringify.
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