如何在Javascript中使用数组作为键?

Bdf*_*dfy 14 javascript

我在python上有一个简单的例子:

programs = {}
if not programs.has_key(( program, time )):
     programs[( program, time )] = 0
programs[( program, time )] = programs[( program, time )] + 1
Run Code Online (Sandbox Code Playgroud)

如何在Javascript中使用数组作为键?

Wal*_*osz 25

这将"奏效".(但我不推荐它)

var a = {};
var b = [1,2,3];    
a[b] = 'hello';

// a[b] evaluates to 'hello'
// a[[1,2,3]] evaluates to 'hello'
// a['1,2,3'] evaluates to 'hello'
Run Code Online (Sandbox Code Playgroud)

它的工作原理是因为当您将数组[1,2,3]作为哈希(map/associative-array)键传递时,在执行哈希查找之前将其转换为字符串'1,2,3'.只要您不需要两个具有相同值的不同数组来映射到不同的哈希值,它就应该满足您的需求.

var c = [1,2,3]
// a[c] evaluates to 'hello' even though we never executed a[c] = 'hello'
// but b == c evaluates to false
// b & c are two separate objects with the same values, so when they
// get converted to a string for hashing, they return the same value from the hash
Run Code Online (Sandbox Code Playgroud)

如上所述,如果要使用对象引用作为键,则需要的不仅仅是标准JavaScript哈希.

更新

根据@speedplane的评论:

我怀疑JS toString()在将数组传递给哈希键时会调用该数组.因此,您可以轻松地测试您实际获得的密钥:

 ["x", "y", "z"].toString;                // 'x,y,z'
 ["x,y,z"].toString();                    // 'x,y,z'
 [1,2,3].toString();                      // '1,2,3'
 [1,2,'3'].toString();                    // '1,2,3'
 [[1],[2],[3]].toString();                // '1,2,3'
 [["x",1], ["y",2], ["z",3]].toString();  // 'x,1,y,2,z,3'
Run Code Online (Sandbox Code Playgroud)

所以,我建议你不要这样做,除非你真的了解发生了什么.即便如此,我也不会这样做.

  • 请注意,如果您使用字符串数组作为键,这不会很好地工作。例如,`var a={}; var b = ["x", "y", "z"]; var c = ["x,y,z"]; a[b] = '哦哦'; a[c]` 将评估为 `uh oh`。两个不同的数组 `b` 和 `c` 映射到相同的对象键。 (4认同)

Rob*_*b W 13

JavaScript键是字符串.

您需要一个WeakMap或自定义方法将数组映射到其他对象.

  • map.set([1,2],'woo'); map.get([1,2]) - > undefined.有没有办法以这种方式使用数组? (6认同)
  • `[1,2]`和`[1,2]`是不同的对象.使用`var arr = [1,2];``map.set(arr,'woo');`和`map.get(arr,'woo');`.如果你不能保留对数组的引用,那么你必须以某种方式序列化/散列它.天真地,例如使用`arr.join(',')`作为关键. (5认同)

Ank*_*nko 7

我编写了一个名为array-keyed-map的库,用于在现代 JavaScript 中稳健地执行此操作。与迄今为止发布的其他答案不同,它不依赖于将值序列化为字符串,而是使用 ES2015Map对象,该对象可以接受任意值作为键。

我将引用我对另一个问题的回答以获得实现概述,因此该方法将被保留,以防库因某种原因消失,或者您想自己实现它:

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

  • 在内部声明的Symbol键下:树中该点的值(如果有)。在Symbol保证唯一性,所以没有用户提供的价值可以覆盖这个关键。

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

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

'a':
  [value]: undefined
  'b':
    [value]: true
Run Code Online (Sandbox Code Playgroud)

akmap.set(['a'], 'okay')之后做只会改变路径的值'a'

'a':
  [value]: 'okay'
  'b':
    [value]: true
Run Code Online (Sandbox Code Playgroud)

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

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


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


小智 -2

这对你有用吗?

jsfiddle

<script>
var ary = {person1:'valerie', person2:'alex'};
for (key in ary) {
    document.write(key, '<br>')
}

document.write(ary['person2'], '<br>')
</script>
Run Code Online (Sandbox Code Playgroud)