Usando um inteiro como uma chave em uma matriz associativa em JavaScript

102

Quando eu crio um novo array JavaScript e uso um inteiro como chave, cada elemento desse array até o inteiro é criado como indefinido.

Por exemplo:

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

irá imprimir 2298 undefined's e um 'Some string'.

Como devo fazer com que o JavaScript use 2300 como uma string em vez de um inteiro, ou como devo evitar que instancie 2299 índices vazios?

Peter Mortensen
fonte

Respostas:

128

Use um objeto, como as pessoas estão dizendo. No entanto, observe que você não pode ter chaves inteiras. JavaScript irá converter o inteiro em uma string . Os seguintes resultados são 20, não indefinidos:

var test = {}
test[2300] = 20;
console.log(test["2300"]);
Claudiu
fonte
12
+1 Observe que isso é verdade até mesmo para Arrays! consulte stackoverflow.com/questions/1450957/…
bobince
1
@bobince: Internamente, claro. No entanto, logicamente , os arrays têm "chaves" inteiras.
Lightness Races in Orbit
1
Observe que usar um inteiro como chave mudará o comprimento do seu array. Você definitivamente deve usar Object em vez disso. Eu só queria usar o id do Facebook como chave, e JSON.stringify travaria minha máquina;)
Krystian
2
@LightnessRacesinOrbit Os detalhes internos ainda podem vazar e morder você. Veja esta versão simplificada do que encontrei hoje: jsfiddle.net/cincodenada/pseujLex/2 Pode parecer artificial quando reduzido, mas era uma parte sensata de um script maior (e é um pouco menos planejado no CoffeeScript: jsfiddle.net/ cincodenada / oojr7Ltn / 2 ). Esse aparente detalhe de implementação me custou um bom bocado de caça aos bugs hoje.
cincodenada de
1
Uma pequena nota para números não inteiros: 0.25e .25resolva para a mesma string "0.25". Então, se você estiver usando chaves fracionários, você pode recuperar a propriedade de uma chave numérica definida 0.25usando 0.25, .25, "0.25"mas não ".25".
Sandy Gifford,
34

Você pode apenas usar um objeto:

var test = {}
test[2300] = 'Some string';
Annie
fonte
16
Ainda é lançado em cadeia.
desenhou 010 de
1
@ drew010 sim, os objetos Javascript permitem indexação apenas com strings.
Pithikos 01 de
22

Como as pessoas dizem, o JavaScript irá converter uma string de número em inteiro, então não é possível usar diretamente em uma matriz associativa, mas os objetos funcionarão para você de maneira semelhante, eu acho.

Você pode criar seu objeto:

var object = {};

E adicione os valores conforme a matriz funciona:

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

Isso lhe dará:

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

Depois disso, você pode acessá-lo como um array em outras línguas obtendo a chave:

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

Eu testei e funciona.

Jesuslg123
fonte
17

Se o caso de uso estiver armazenando dados em uma coleção, o ECMAScript 6 fornece o Maptipo.

É apenas mais pesado para inicializar.

Aqui está um exemplo:

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)})`);
}

Resultado:

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

Compilando outras respostas:

Objeto

var test = {};

Ao usar um número como a chave de uma nova propriedade, o número se transforma em uma string:

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

Ao acessar o valor da propriedade usando o mesmo número, o número é transformado em string novamente:

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

Ao obter as chaves do objeto, no entanto, elas não serão transformadas em números:

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

Mapa

ECMAScript 6 permite o uso do objeto Map ( documentação , uma comparação com Object ). Se seu código deve ser interpretado localmente ou se a tabela de compatibilidade ECMAScript 6 parece verde o suficiente para seus objetivos, considere o uso de um mapa:

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

Nenhuma conversão de tipo é realizada, para o melhor ou para o pior:

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

Use um objeto em vez de uma matriz. Arrays em JavaScript não são arrays associativos. Eles são objetos com magia associada a quaisquer propriedades cujos nomes pareçam inteiros. Essa mágica não é o que você deseja se não os estiver usando como uma estrutura tradicional semelhante a um array.

var test = {};
test[2300] = 'some string';
console.log(test);
bdukes
fonte
1
Eles podem ser arrays associativos, mas apenas porque também são objetos que podem ter um conjunto de propriedades nomeadas. Mas isso só torna as coisas ridiculamente confusas e, portanto, sim, os objetos são muito melhores de usar.
Graza
Os arrays nunca podem ser Graza associativos. Se você tentar usar chaves em um array e depois iterar sobre eles, notará que também está iterando por meio de todos os métodos e propriedades padrão dos arrays -> não muito desejável.
Swizec Teller
@Swizec - exatamente por que eu disse "ridiculamente confuso". Você pode usar um array como um array associativo - isto é, como pares nome / valor, mas você nunca iria querer iterá-los! (Eu estava simplesmente apontando um
detalhe
sim, mas ao iterar, eles não estão em uma ordem específica (ou seja, a ordem não é garantida), que seria o ponto de numerá-los, então é muito pior do que apenas confundir.
Julix
3

Tente usar um objeto, não um array:

var test = new Object(); test[2300] = 'Some string';
Jeff Hammerbacher
fonte
3
Este é definitivamente o caminho a seguir. Dessa forma, você não criará uma matriz longa de 2300 entradas para armazenar uma única string.
Krystian
2
Arrays JS @Krystian são arrays falsos. Execute var a = []; a[Math.pow(2, 30)] = 'hello';e você não verá o uso do navegador / memória aumentar em mais de um gigabyte, mas verá que a.lengthé 1073741824. As VMs armazenam claramente alguns "arrays" usando alguma outra estrutura de dados, suponho que seja simplesmente um hashtable, pelo menos se eles são suficientemente esparsos.
Andy
2

Obtenha o valor de uma propriedade de matriz associativa quando o nome da propriedade for um inteiro:

Começando com uma matriz associativa em que os nomes das propriedades são inteiros:

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

Envie itens para a matriz:

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

Faça um loop pela matriz e faça algo com o valor da propriedade.

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
    }
}

A saída do console deve ser assim:

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

Como você pode ver, você pode contornar a limitação da matriz associativa e ter um nome de propriedade um inteiro.

NOTA: O array associativo em meu exemplo é o conteúdo JSON que você teria se serializasse um objeto Dictionary <string, string> [].

Jason Williams
fonte
0

Use um objeto - com um inteiro como chave - em vez de uma matriz.

Estágio superior
fonte
0

Às vezes eu uso prefixos para minhas chaves. Por exemplo:

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

obj = {};

obj[key] = val;

Agora você não tem nenhum problema para acessá-los.

pictus
fonte