Map using tuples or objects
dictionary, ecmascript-harmony, equality, javascript
Solution
Ok, I've raised the issue on esdiscuss now and I got an answer from Mozilla's Jason Orendorff:
- This is a problem with ES6 maps.
- The solution will come in the form of ES7 value objects for keys instead of objects.
- It was considered before to let people specify `.equals` and `.hashCode` but it was rejected in favor of value objects. (for good reasons in my opinion).
- The only solution as of now is to roll your own collection.
A basic such collection (concept, don't use in production code) was offered by Bradley on the ESDiscuss thread and might look something like this:
function HashMap(hash) {
var map = new Map;
var _set = map.set;
var _get = map.get;
var _has = map.has;
var _delete = map.delete;
map.set = function (k,v) {
return _set.call(map, hash(k), v);
}
map.get = function (k) {
return _get.call(map, hash(k));
}
map.has = function (k) {
return _has.call(map, hash(k));
}
map.delete = function (k) {
return _delete.call(map, hash(k));
}
return map;
}
function TupleMap() {
return new HashMap(function (tuple) {
var keys = Object.keys(tuple).sort();
return keys.map(function (tupleKey) { // hash based on JSON stringification
return JSON.stringify(tupleKey) + JSON.stringify(tuple[tupleKey]);
}).join('\n');
return hashed;
});
}
A better solution is to use something like MontageJS/Collections which allows for specification of hash/equals functions.
You can see the API docs here.
Problem
I'm trying to use the new (ES6) `Map` objects in order to represent a map between properties and a value. I have objects in a form similar to: ``` {key1:value1_1,key2:value2_1},..... {key1:value1_N,key2:value2_N} ``` I want to group them based on both their key1 and key2 value. For example, I want to be able to group the following by `x` and `y`: ``` [{x:3,y:5,z:3},{x:3,y:4,z:4},{x:3,y:4,z:7},{x:3,y:1,z:1},{x:3,y:5,z:4}] ``` And obtain a Map containing: ``` {x:3,y:5} ==> {x:3,y:5,z:3},{x:3,y:5,z:4} {x:3,y:4} ==> {x:3,y:4,z:4},{x:3,y:4,z:7} {x:3,y:1} ==> {x:3,y:1,z:1} ``` In Python, I'd use tuples as dictionary keys. ES6 map allow arbitrary objects as keys but use the standard equality algorithm (`===`) so objects are only equal by reference from what I can tell. How can I accomplish this sort of grouping using ES6 maps? Alternatively, a solution using normal JS objects if there is an elegant way I overlooked. I'd rather not use an external collections library - but if there is a better solution using one I'm interested in learning about it too.