I am using Javascript ES6 features in a node.js application:
class pairKey {
constructor(x_pos, y_pos) {
this._X = x_pos;
this._Y = y_pos;
}
get x() {
return this._X;
}
set x(x_pos) {
this._X = x_pos;
}
get y() {
return this._Y;
}
set y(y_pos) {
this._Y = y_pos;
}
var allElem = new Map();
allElem.set(new pairKey(1,2), 'a');
allElem.set(new pairKey(2,3), 'b');
console.log(allElem.has(new pairKey(1,2))); //Should return true instead return false
In this code I want to use a pair of Int
as key of my map (allElem
).
The problem is that I don't know how Map
compare objects in javascript.
Someone can help me?
Map objects are collections of key-value pairs. A key in the Map may only occur once; it is unique in the Map 's collection. A Map object is iterated by key-value pairs — a for...of loop returns a 2-member array of [key, value] for each iteration.
One approach to solve this would be to take the map. entries() , create array from it, then sort that array by keys. And do the same thing with the other map. And then loop through those two arrays to compare them.
The Map. keys() method is used to extract the keys from a given map object and return the iterator object of keys. The keys are returned in the order they were inserted.
Few basic differences are as follows: In Object, the data-type of the key-field is restricted to integer, strings, and symbols. Whereas in Map, the key-field can be of any data-type (integer, an array, even an object!) In the Map, the original order of elements is preserved.
The reason your code fails is that Map uses same-value algorithm to match keys. An object instance is not the same value as another object instance, even if both share the same intrinsic value (for examle, try ({a:1} === {a:1})
-> it's false). One way you could make that work for you is to add a key property to your object such that the same intrinsic values generate the exact same key (1 to 1). Then use that key when setting Map entries. See example (Utilizes Symbol.for
to generate a reproducable key):
'use strict'
class pairKey {
constructor(x_pos, y_pos) {
this._X = x_pos;
this._Y = y_pos;
}
get x() {
return this._X;
}
set x(x_pos) {
this._X = x_pos;
}
get y() {
return this._Y;
}
set y(y_pos) {
this._Y = y_pos;
}
get key() {
return Symbol.for(`pairKey[${this.x}:${this.y}]`);
}
}
var allElem = new Map();
allElem.set(new pairKey(1, 2).key, 'a');
allElem.set(new pairKey(2, 3).key, 'b');
console.log(allElem.has(new pairKey(1, 2).key));
Map
does use the SameValueZero algorithm for comparing the keys. This means that reference equality is used for objects, so if you have a = new PairKey(1, 2)
and b = new PairKey(1, 2)
they are not the same object - a !== b
.
So what can you do to solve this? There are basically two ways to solve this:
new PairKey
always returns the same object if called with the same argumentsAlso you might be able to subclass Map
where all methods are overwritten so that they handle PairKey
s specially, relying on one of the above techniques.
Unfortunately, hash consing is impossible to implement without weak references and without leaking memory, so we'll have to resort to the first technique:
class Pair {
constructor(x, y) {
this.x = x;
this.y = y;
}
toKey() {
return `Pair(${this.x}, ${this.y})`;
}
static key(x, y) {
return new Pair(x, y).toKey();
}
}
var allElem = new Map(); // string -> string
allElem.set(Pair.key(1, 2), 'a');
allElem.set(Pair.key(2, 3), 'b');
console.log(allElem.has(Pair.key(1, 2))); // true
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