I have a simple example on python:
programs = {}
if not programs.has_key(( program, time )):
programs[( program, time )] = 0
programs[( program, time )]
JavaScript keys are strings.
You need a WeakMap, or a custom method to map arrays to other objects.
Will this do the trick for you?
jsfiddle
<script>
var ary = {person1:'valerie', person2:'alex'};
for (key in ary) {
document.write(key, '<br>')
}
document.write(ary['person2'], '<br>')
</script>
I've written a library called array-keyed-map for 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.
I'll quote my answer to a different question for 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.
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.
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.
Based on the comment from @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:
["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 really understand what is going on. And even then, I wouldn't do it.