Javascript 如何在Javascript中使用数组作为键?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10173956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use array as key in Javascript?
提问by Bdfy
I have a simple example on python:
我有一个关于python的简单示例:
programs = {}
if not programs.has_key(( program, time )):
programs[( program, time )] = 0
programs[( program, time )] = programs[( program, time )] + 1
How to use array as key in Javascript ?
如何在 Javascript 中使用数组作为键?
采纳答案by Ryan Fiorini
回答by Walter Stabosz
This will "work". (but I don't recommend it)
这将“工作”。(但我不推荐)
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'
It works because when you pass the array [1,2,3] as the hash (map/associative-array) key, is being converted to the string '1,2,3' before performing the hash lookup. It should suit your needs as long as you don't need two different arrays of the same value to map to different hash values.
它起作用是因为当您将数组 [1,2,3] 作为哈希(映射/关联数组)键传递时,在执行哈希查找之前将被转换为字符串 '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
As it was mentioned, you'll need more than the standard JavaScript hash if you want to use object references as your keys.
正如前面提到的,如果你想使用对象引用作为你的键,你需要的不仅仅是标准的 JavaScript 哈希。
Update
更新
Based on the comment from @speedplane:
根据@speedplane 的评论:
I suspect that JS calls toString()
on the array when you pass it into a hash key. So you can easily test what you're actually going to get as your key:
我怀疑toString()
当您将数组传递给哈希键时,JS 会调用该数组。因此,您可以轻松测试您实际将获得的密钥:
["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'
So again, I recommend that you don't do this unless you reallyunderstand what is going on. And even then, I wouldn't do it.
因此,我再次建议您不要这样做,除非您真的了解正在发生的事情。即使那样,我也不会这样做。
回答by Rob W
回答by Anko
I've written a library called array-keyed-mapfor doing this robustly in modern JavaScript. Unlike the other answers so far posted, it does not rely on serialising values into strings, but instead uses ES2015 Map
objects, which can accept arbitrary values as keys.
我编写了一个名为array-keyed-map的库,用于在现代 JavaScript 中稳健地执行此操作。与迄今为止发布的其他答案不同,它不依赖于将值序列化为字符串,而是使用 ES2015Map
对象,该对象可以接受任意值作为键。
I'll quote my answer to a different questionfor an implementation overview, so the method is preserved posterity in case the library disappears for some reason, or you want to implement it yourself:
我将引用我对另一个问题的回答以获得实现概述,因此该方法将被保留,以防库因某种原因消失,或者您想自己实现它:
Maintain a tree of
Map
objects. Each tree stores:
Under an internally-declared
Symbol
key: The value at that point in the tree (if any). TheSymbol
guarantees uniqueness, so no user-provided value can overwrite this key.On all its other keys: all other so-far set next-trees from this tree.
For example, on
akmap.set(['a', 'b'], true)
, the internal tree structure would be like—'a': [value]: undefined 'b': [value]: true
Doing
akmap.set(['a'], 'okay')
after that would just change the value for the path at'a'
:'a': [value]: 'okay' 'b': [value]: true
To get the value for an array, iterate through the array while reading the corresponding keys off the tree. Return
undefined
if the tree at any point is non-existent. Finally, read the internally declared[value]
symbol off the tree you've gotten to.To delete a value for an array, do the same but delete any values under the
[value]
-symbol-key, and delete any child trees after the recursive step if they ended up with asize
of 0.Why a tree? Because it's very efficient when multiple arrays have the same prefixes, which is pretty typical in real-world use, for working with e.g. file paths.
维护
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下的所有值,并在递归步骤之后删除所有子树,如果它们以 asize
为 0结束。为什么是一棵树?因为当多个数组具有相同的前缀时非常有效,这在实际使用中非常典型,用于处理例如文件路径。