【问题标题】:Using Array objects as key for ES6 Map使用 Array 对象作为 ES6 Map 的键
【发布时间】:2015-12-16 02:02:47
【问题描述】:

我正在尝试将我的代码更新到 ES6,因为我使用的是 Node 4.0,并且到目前为止我真的很喜欢它的功能。但是我对新的 ES6 Map 数据结构有问题,因为当使用 Array 作为键时,它的行为与 {} 不同。我将它用作反地图。

我运行这段代码,我想知道如何使用数组作为Map 的键。

"use strict";

var a = new Map();
a.set(['x','y'], 1);
console.log(a.get(['x','y']));

var b = {};
b[['x','y']] = 1;

console.log(b[['x','y']]);

它打印出以下内容,第一行应该是1 而不是undefined

undefined
1

原始的 JS 映射对键进行字符串化,我不想使用新的 ES6 Map 进行相同类型的字符串化破解。

对于 ES6 Map,如何可靠地使用数组作为键?

【问题讨论】:

  • TL;DR: JavaScript 中的集合 all 将数组键转换为字符串...因此您只有两种可能性: A. 使用字符串 (考虑到 JS 集合无论如何都会这样做,如果你正在做一个元组,这可能不是一个糟糕的方法,即key.split(",")[0] key.split(",")[1]),或者 B. 拆分数组并将其元素相互映射和子映射,就像anko 的回答 + arrayed-keyed-map 确实...

标签: javascript arrays dictionary ecmascript-6 es6-map


【解决方案1】:

了解 ES2015 Map 键的比较(几乎)就像与 === 运算符一样。两个数组实例,即使它们包含相同的值,也永远不会以=== 相互比较。

试试这个:

var a = new Map(), key = ['x', 'y'];
a.set(key, 1);
console.log(a.get(key));

由于 Map 类旨在用作基类,因此您可以实现具有覆盖 .get() 函数的子类,也许。

(第一句中的“几乎”是为了反映 Map 键相等比较是通过Object.is() 完成的,这在日常编码中很少出现。它本质上是一个三分之一 JavaScript 中相等性测试的变体。)

【讨论】:

  • 感谢您的详细回答,但覆盖 .get() 不是我想要做的
【解决方案2】:

我也有这个需求,所以我写了一个 ISC 授权的库:array-keyed-map。你可以find it on npm。我认为the source 很清楚,但无论如何它是这样工作的,为了后代:


维护Map 对象的树。每棵树存储:

  • 在内部声明的Symbol 键下:树中该点的值(如果有)。 Symbol 保证唯一性,因此任何用户提供的值都不能覆盖此键。

  • 在它的所有其他键上:到目前为止所有其他从这棵树设置下一个树。

例如,在akmap.set(['a', 'b'], true) 上,内部树结构将是——

'a':
  [value]: undefined
  'b':
    [value]: true

之后执行akmap.set(['a'], 'okay') 只会更改'a' 处的路径值:

'a':
  [value]: 'okay'
  'b':
    [value]: true

要获取数组的值,请在从树中读取相应键的同时遍历数组。如果任何点的树都不存在,则返回 undefined。最后,从你到达的树上读取内部声明的 [value] 符号。

要删除数组的值,请执行相同操作,但删除[value]-symbol-key 下的所有值,并在递归步骤后删除所有子树,如果它们的size 为0。


为什么是树?因为当多个数组具有相同的前缀时它非常有效,这在实际使用中非常典型,例如使用文件路径。

【讨论】:

    【解决方案3】:

    您需要保存对您用作键的Array 的非原始实例的引用。请注意以下两个示例的区别:

    "use strict";
    
    var a = new Map();
    a.set(['x','y'], 1);
    console.log(a.get(['x','y']));
    console.log(['x','y'] === ['x','y']);
    
    var b = new Map();
    var array = ['x','y'];
    b.set(array, 1);
    console.log(b.get(array));
    console.log(array === array);

    【讨论】:

      【解决方案4】:

      如果有人在这里寻找更基本的方法,您可以应用自定义的 1 对 1 键到字符串的转换,例如 ${x}_${y}(依赖于特定的键结构)或 JSON.stringify(key)(更通用)——这绝不是一个完美的解决方案,但在许多情况下它可能是最可靠的。

      我知道 OP 要求其他方法,但我认为这里仍然需要提到这个方法,作为对标题问题的最直接答案。

      【讨论】:

        猜你喜欢
        • 2017-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-13
        • 1970-01-01
        • 2022-07-12
        相关资源
        最近更新 更多