Utilizzo di un numero intero come chiave in un array associativo in JavaScript


102

Quando creo un nuovo array JavaScript e utilizzo un numero intero come chiave, ogni elemento di quell'array fino all'intero viene creato come non definito.

Per esempio:

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

produrrà 2298 undefined e una "Some string".

Come dovrei fare in modo che JavaScript utilizzi 2300 come stringa invece di un numero intero, o come dovrei impedire che istanziasse 2299 indici vuoti?

Risposte:


128

Usa un oggetto, come dicono le persone. Tuttavia, nota che si può non avere integer chiavi. JavaScript convertirà l'intero in una stringa . Le seguenti uscite 20, non indefinite:

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

12
+1 Nota che questo vale anche per gli array! vedi stackoverflow.com/questions/1450957/…
bobince

1
@ Bobince: internamente, certo. Tuttavia, logicamente , gli array hanno "chiavi" intere.
Gare di leggerezza in orbita il

1
Tieni presente che l'utilizzo di integer come chiave cambierà la lunghezza del tuo array. Dovresti assolutamente usare Object invece. Volevo solo usare l'ID di Facebook come chiave e JSON.stringify avrebbe bloccato la mia macchina;)
Krystian

2
@LightnessRacesinOrbit I dettagli interni possono ancora fuoriuscire e morderti però. Guarda questa versione semplificata di ciò in cui mi sono imbattuto oggi: jsfiddle.net/cincodenada/pseujLex/2 Può sembrare artificioso quando ridotto, ma era una parte sensata di uno script più grande (ed è un po 'meno artificioso in CoffeeScript: jsfiddle.net/ cincodenada / oojr7Ltn / 2 ). Questo apparente dettaglio di implementazione mi è costato un bel po 'di ricerca di bug oggi.
cincodenada

1
Una piccola nota per i numeri non interi: 0.25e .25risolviamo con la stessa stringa "0.25". Quindi, se si sta utilizzando i tasti frazionali, è possibile recuperare la proprietà di un tasto numerico impostato 0.25utilizzando 0.25, .25, "0.25"ma non ".25".
Sandy Gifford

34

Puoi semplicemente usare un oggetto:

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

16
Viene ancora trasmesso alla stringa.
pareggiò 010

1
@ drew010 sì, gli oggetti Javascript consentono l'indicizzazione solo con stringhe.
Pithikos

22

Come si dice, JavaScript convertirà una stringa di numeri in un numero intero, quindi non è possibile utilizzarlo direttamente su un array associativo, ma penso che gli oggetti funzioneranno in modo simile.

Puoi creare il tuo oggetto:

var object = {};

E aggiungi i valori mentre l'array funziona:

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

Questo ti darà:

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

Dopodiché puoi accedervi come un array in altre lingue ottenendo la chiave:

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

Ho provato e funziona.


17

Se il caso d'uso è l'archiviazione dei dati in una raccolta, ECMAScript 6 fornisce il Maptipo.

È solo più pesante da inizializzare.

Ecco un esempio:

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

Risultato:

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

11

Compilare altre risposte:

Oggetto

var test = {};

Quando si utilizza un numero come chiave di una nuova proprietà, il numero si trasforma in una stringa:

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

Quando si accede al valore della proprietà utilizzando lo stesso numero, il numero viene nuovamente trasformato in una stringa:

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

Quando si ottengono le chiavi dall'oggetto, tuttavia, non verranno trasformate di nuovo in numeri:

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

Carta geografica

ECMAScript 6 consente l'utilizzo dell'oggetto Map ( documentazione , confronto con Object ). Se il tuo codice deve essere interpretato localmente o la tabella di compatibilità ECMAScript 6 sembra abbastanza verde per i tuoi scopi, considera l'utilizzo di una mappa:

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

Non viene eseguita alcuna conversione di tipo, nel bene e nel male:

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

4

Usa un oggetto invece di un array. Gli array in JavaScript non sono array associativi. Sono oggetti con la magia associata a qualsiasi proprietà i cui nomi sembrano numeri interi. Quella magia non è quello che vuoi se non li stai usando come una tradizionale struttura a matrice.

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

1
Essi possono essere array associativi, ma solo perché sono anche oggetti che possono essere denominate proprietà impostate. Ma questo rende le cose ridicolmente confuse, quindi sì, gli oggetti sono molto meglio da usare.
Graza

Gli array non possono mai essere Graza associativi. Se provi a usare le chiavi in ​​un array e poi ripeti su di esse, noterai che stai anche iterando attraverso tutti i metodi e le proprietà predefiniti degli array -> non molto desiderabile.
Swizec Teller

@Swizec - esattamente perché ho detto "incredibilmente confuso". È possibile utilizzare un array come un array associativo - che sia il più coppie nome / valore, ma si vorrebbe mai iterare loro! (Stavo semplicemente sottolineando un tecnicismo, sicuramente non qualcosa che consiglierei affatto di fare)
Graza

sì, ma durante l'iterazione non sono in un ordine particolare (cioè l'ordine non è garantito), che sarebbe il punto di numerarli, quindi è molto peggio che confondere.
Julix

3

Prova a utilizzare un oggetto, non un array:

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

3
Questa è decisamente la strada da percorrere. In questo modo non creerai un array lungo 2300 voci per memorizzare una singola stringa.
Krystian

2
Gli array @Krystian JS sono falsi array. Run var a = []; a[Math.pow(2, 30)] = 'hello';e non vedranno l'utilizzo del browser riprese / memoria fino di oltre un gigabyte, ma vedrete a.lengthè 1073741824. VM chiaramente memorizzare alcuni "array" con qualche altra struttura di dati, sto cercando di indovinare semplicemente una tabella hash, almeno se sono sufficientemente rade.
Andy

2

Ottieni il valore per una proprietà di matrice associativa quando il nome della proprietà è un numero intero:

A partire da un array associativo in cui i nomi delle proprietà sono numeri interi:

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

Invia elementi all'array:

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

Scorri l'array e fai qualcosa con il valore della proprietà.

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

L'output della console dovrebbe essere simile a questo:

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

Come puoi vedere, puoi aggirare la limitazione degli array associativi e fare in modo che il nome di una proprietà sia un numero intero.

NOTA: l'array associativo nel mio esempio è il contenuto JSON che avresti se serializzassi un oggetto Dictionary <string, string> [].


0

Usa un oggetto - con un numero intero come chiave - piuttosto che un array.


0

A volte uso un prefisso per le mie chiavi. Per esempio:

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

obj = {};

obj[key] = val;

Ora non hai alcun problema ad accedervi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.