JavaScript:使用元组作为字典键

35

我有这样的情况,我想要创建一个从元组到整数的映射。在Python中,我会简单地将元组(a,b)作为字典的键。

JavaScript有元组吗?我发现在JavaScript中(a,b)只返回b(最后一个项目),这似乎是从C继承而来的。

所以,作为解决方法,我想可以使用数组代替元组。

my_map[[a,b]] = c

我在Firebug控制台尝试了一下,似乎可以工作。那是一个好的方法吗?

另一种我想到的选择是将元组转换为字符串。

my_map[""+a+":"+b] = c

所以问题是:这些方法中是否存在任何问题?有更好的方法吗?

编辑:

小澄清:在我的情况下,a、b、c都是整数。

4个回答

23

EcmaScript将通过名称或[]来索引属性视为相同,例如:

a.name

字面上等同于

a["name"]
唯一的不同之处在于数字等不是命名属性访问中有效的语法。
a.1
a.true

等等,所有这些都是无效的语法。

遗憾的是,所有这些索引机制之所以相同,是因为在EcmaScript中,所有属性名称都是字符串,例如:

a[1]

被有效地解释为

a[String(1)]

这意味着在您的示例中,您执行以下操作:

my_map[[a,b]] = c

变成了什么?

my_map[String([a,b])] = c

这本质上与你的第二个示例所做的相同(根据实现方式,它可能更快)。

如果你想要真正的值关联查找,你需要在js语言的基础上自己实现它,但你会失去方便的[]样式访问 :-(


4
虽然在技术上是正确的,但我想警告不要实际使用语法a[1],因为它看起来太像数组解引用了。如果涉及的对象实际上是Array类的一个实例,那么您会自食其果。 - Guss
@Guss 抱歉,你能更好地解释一下吗?我是js语言的新手,还没有理解你的观点。 - nkint
5
我只是在说,人们不应该将数字用作属性引用,除非他们特别想通过索引访问数组成员。否则,代码会难以理解和混乱。例如: var objA = { "1": "abc", "3": "def" };var objA = [ "abc", undefined, "def" ]; 两者都可以使用 objA[1]objA[3],但只有一个真正是具有像 push()length 等数组字段的数组。 - Guss

7
您可以使用我的jshashtable,然后使用任何对象作为键,但是假设您的元组是整数数组,我认为最好的选择是使用您自己提到的方法:使用Array的join()方法创建正常对象的属性名称。您可以非常简单地包装它:
function TupleDictionary() {
 this.dict = {};
}

TupleDictionary.prototype = {
 tupleToString: function(tuple) {
  return tuple.join(",");
 },

 put: function(tuple, val) {
  this.dict[ this.tupleToString(tuple) ] = val;
 },

 get: function(tuple) {
  return this.dict[ this.tupleToString(tuple) ];
 }
};

var dict = new TupleDictionary();
dict.put( [1,2], "banana" );
alert( dict.get( [1,2] ) );

5
所有的Javascript对象键都是字符串。使用my_map[[a,b]] = c将产生一个在my_map中的键,它的结果是[a,b].toString()a.toString() + ',' + b.toString()。这可能是有意的(并且类似于您使用的a + ':' + b),但如果您的键包含分隔符(使用数组作为键时为逗号,如果您按照示例中所示编写字符串,则为冒号),则可能会遇到冲突。
编辑:另一种方法是保留一个单独的用于键引用的数组。例如:
var keys = [
    [a,b],
    [c,d]
];
var my_map = {
    'keys[0]': /* Whatever [a,b] ought to be the key for */,
    'keys[1]': /* Whatever [c,d] ought to be the key for */
};

1

实现类似功能最简单和“自然”的方法是使用多维数组,就像这样:

var my_map = [["blah","blah","bla"],
              ["foo", "bla", 8],
              [324, 2345, 235],
              [true, false, "whatever..."]];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接