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.

Original source