使用元组或对象映射

Ben*_*aum 30 javascript equality map ecmascript-harmony

我正在尝试使用新的(ES6)Map对象来表示属性和值之间的映射.

我有类似于以下形式的对象:

 {key1:value1_1,key2:value2_1},..... {key1:value1_N,key2:value2_N}
Run Code Online (Sandbox Code Playgroud)

我想根据key1 key2值它们进行分组.

举例来说,我希望能够以组以下的xy:

[{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}]
Run Code Online (Sandbox Code Playgroud)

并获取包含以下内容的Map:

{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}
Run Code Online (Sandbox Code Playgroud)

在Python中,我使用元组作为字典键.ES6映射允许任意对象作为键,但使用标准相等算法(===),因此对象只能通过引用来区分我所知道的.

如何使用ES6地图完成这种分组?或者,如果有一种我忽略的优雅方式,使用普通JS对象的解决方案.

我宁愿不使用外部集合库 - 但如果有一个更好的解决方案使用我也有兴趣了解它.

Ben*_*aum 18

好吧,我现在提出了关于es escucuss的问题,我得到了Mozilla的Jason Orendorff的回答:

  1. ES6地图的问题.
  2. 解决方案将以密钥而非对象的ES7 值对象的形式出现.
  3. 之前考虑过让人们指定.equals,.hashCode但是它被拒绝而不是有价值的对象.(我认为有充分理由).
  4. 截至目前唯一的解决方案是推出自己的收藏品.

Bradley在ESDiscuss主题上提供了一个基本的集合(概念,不要在生产代码中使用),可能看起来像这样:

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;
  });
}
Run Code Online (Sandbox Code Playgroud)

更好的解决方案是使用MontageJS/Collections之类的东西,它允许指定hash/equals函数.

您可以在此处查看API文档.


Ry-*_*Ry- 7

这似乎不太方便.你能做什么?像往常一样可怕的东西.

let tuple = (function() {
    let map = new Map();

    function tuple() {
        let current = map;
        let args = Object.freeze(Array.prototype.slice.call(arguments));

        for (let item of args) {
            if (current.has(item)) {
                current = current.get(item);
            } else {
                let next = new Map();
                current.set(item, next);
                current = next;
            }
        }

        if (!current.final) {
            current.final = args;
        }

        return current.final;
    }

    return tuple;
})();
Run Code Online (Sandbox Code Playgroud)

瞧.

let m = new Map();
m.set(tuple(3, 5), [tuple(3, 5, 3), tuple(3, 5, 4)]);
m.get(tuple(3, 5)); // [[3, 5, 3], [3, 5, 4]]
Run Code Online (Sandbox Code Playgroud)