在JavaScript的关联数组中使用整数作为键


102

当我创建一个新的JavaScript数组并使用整数作为键时,该数组中直到该整数的每个元素都将被创建为undefined。

例如:

var test = new Array();
test[2300] = 'Some string';
console.log(test);

将输出2298个未定义的和一个“某些字符串”。

如何使JavaScript使用2300作为字符串而不是整数,或者如何避免实例化2299空索引?

Answers:


128

就像人们所说的那样使用对象。但是,请注意,不能有整数键。JavaScript会将整数转换为字符串。以下输出20(未定义):

var test = {}
test[2300] = 20;
console.log(test["2300"]);

12
+1请注意,这甚至适用于数组!看到stackoverflow.com/questions/1450957/...
bobince

1
@bobince:在内部,确定。但是,从逻辑上讲,数组具有整数“键”。
Lightness Races in Orbit

1
请注意,使用整数作为键将更改数组的长度。您绝对应该使用Object代替。我只是想使用facebook id作为密钥,而JSON.stringify会使我的机器崩溃;)
Krystian

2
@LightnessRacesinOrbit内部细节仍然可能泄漏并咬你。请参阅我今天遇到的这个简化版本:jsfiddle.net/cincodenada/pseujLex/2简化后似乎有些人为,但它是较大脚本的明智部分(在CoffeeScript中人为少一些):jsfiddle.net/ cincodenada / oojr7Ltn / 2)。今天,这种看似实现的细节使我花了很多时间去寻找错误。
cincodenada 2014年

1
关于非整数的一点说明: 0.25.25解析为相同的字符串"0.25"。所以,如果你正在使用小数键,你可以检索一个数值设置键的财产0.25使用0.25.25"0.25"但不是".25"
桑迪·吉福德

34

您可以只使用一个对象:

var test = {}
test[2300] = 'Some string';

16
仍然被转换为字符串。
drew010 '16

1
@ drew010是的,Javascript对象仅允许使用字符串进行索引。
Pithikos

22

就像人们说的那样,JavaScript会将数字字符串转换为整数,因此不可能直接在关联数组上使用,但是对象将以我认为的类似方式为您工作。

您可以创建对象:

var object = {};

并将值添加为数组的工作原理:

object[1] = value;
object[2] = value;

这将为您提供:

{
  '1': value,
  '2': value
}

之后,您可以像其他语言的数组一样访问它,获取密钥:

for(key in object)
{
   value = object[key] ;
}

我已经测试过并且可以工作。


17

如果用例将数据存储在集合中,则ECMAScript 6提供Map类型。

初始化只会更重。

这是一个例子:

const map = new Map();
map.set(1, "One");
map.set(2, "Two");
map.set(3, "Three");

console.log("=== With Map ===");

for (const [key, value] of map) {
    console.log(`${key}: ${value} (${typeof(key)})`);
}

console.log("=== With Object ===");

const fakeMap = {
    1: "One",
    2: "Two",
    3: "Three"
};

for (const key in fakeMap) {
    console.log(`${key}: ${fakeMap[key]} (${typeof(key)})`);
}

结果:

=== With Map ===
1: One (number)
2: Two (number)
3: Three (number)
=== With Object ===
1: One (string)
2: Two (string)
3: Three (string)

11

编译其他答案:

目的

var test = {};

使用数字作为新属性的键时,数字将变成字符串:

test[2300] = 'Some string';
console.log(test['2300']);
// Output: 'Some string'

当使用相同的数字访问属性的值时,该数字将再次变为字符串:

console.log(test[2300]);
// Output: 'Some string'

但是,当从对象获取键时,它们将不会被转换为数字:

for (var key in test) {
    console.log(typeof key);
}
// Output: 'string'

地图

ECMAScript 6允许使用Map对象(文档与Object的比较)。如果您的代码是要在本地解释的,或者ECMAScript 6兼容性表看起来足以满足您的要求,请考虑使用Map:

var test = new Map();
test.set(2300, 'Some string');
console.log(test.get(2300));
// Output: 'Some string'

不管类型是好还是坏,都不会执行类型转换:

console.log(test.get('2300'));
// Output: undefined
test.set('2300', 'Very different string');
console.log(test.get(2300));
// Output: 'Some string'

4

使用对象而不是数组。JavaScript中的数组不是关联数组。它们是带有任何与名称看起来像整数的属性相关联的魔术对象。如果您不将其用作传统的类似数组的结构,那么您就不会想要这种魔术。

var test = {};
test[2300] = 'some string';
console.log(test);

1
它们可以是关联数组,但这仅是因为它们还是可以设置命名属性的对象。但是,这只会使事情变得混乱,因此,是的,使用对象要好得多。
Graza 2010年

数组永远不能是关联的Graza。如果您尝试使用数组中的键然后对其进行迭代,您会发现您还在遍历数组的所有默认方法和属性->不太理想。
Swizec Teller

@Swizec-正是为什么我说“荒谬地令人困惑”。您可以将数组用作关联数组-即作为名称/值对使用,但是您永远不需要迭代它们!(我只是在指出技术性,绝对不是我建议做的事情)
Graza 2010年

是的,但是在迭代时它们并没有特定的顺序(即无法保证顺序),这就是对它们进行编号的要点,因此,比仅是混淆更糟。
Julix

3

尝试使用对象而不是数组:

var test = new Object(); test[2300] = 'Some string';

3
这绝对是要走的路。这样,您将不会创建2300个条目长数组来存储单个字符串。
克里斯蒂安

2
@Krystian JS数组是伪数组。运行var a = []; a[Math.pow(2, 30)] = 'hello';,您不会看到浏览器/内存的使用量猛增超过一千兆字节,但您会看到的a.length是1073741824。VM显然使用其他数据结构存储了一些“数组”,我猜只是一个哈希表,至少他们很稀疏。
安迪2016年

2

当属性名称是整数时,获取关联数组属性的值:

从属性名称为整数的关联数组开始:

var categories = [
    {"1": "Category 1"},
    {"2": "Category 2"},
    {"3": "Category 3"},
    {"4": "Category 4"}
];

将项目推送到数组:

categories.push({"2300": "Category 2300"});
categories.push({"2301": "Category 2301"});

遍历数组并使用属性值执行某些操作。

for (var i = 0; i < categories.length; i++) {
    for (var categoryid in categories[i]) {
        var category = categories[i][categoryid];
        // Log progress to the console
        console.log(categoryid + ": " + category);
        //  ... do something
    }
}

控制台输出应如下所示:

1: Category 1
2: Category 2
3: Category 3
4: Category 4
2300: Category 2300
2301: Category 2301

如您所见,您可以绕开关联数组限制,并将属性名称设置为整数。

注意:在我的示例中,关联数组是序列化Dictionary <string,string> []对象时将拥有的JSON内容。


0

使用对象(以整数作为键)而不是数组。


0

有时,我的密钥使用前缀。例如:

var pre = 'foo',
    key = pre + 1234

obj = {};

obj[key] = val;

现在,您访问它们没有任何问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.