Używanie liczby całkowitej jako klucza w tablicy asocjacyjnej w JavaScript

103

Kiedy tworzę nową tablicę JavaScript i używam liczby całkowitej jako klucza, każdy element tej tablicy aż do liczby całkowitej jest tworzony jako niezdefiniowany.

Na przykład:

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

zwróci 2298 niezdefiniowanych i jeden „jakiś ciąg”.

Jak sprawić, by JavaScript używał 2300 jako ciągu znaków zamiast liczby całkowitej lub jak zapobiec tworzeniu wystąpienia 2299 pustych indeksów?

Peter Mortensen
źródło

Odpowiedzi:

129

Użyj przedmiotu, jak mówią ludzie. Pamiętaj jednak, że możesz nie mieć całkowitą klucze. JavaScript zamieni liczbę całkowitą na łańcuch . Następujące wyjścia 20, nieokreślone:

var test = {}
test[2300] = 20;
console.log(test["2300"]);
Claudiu
źródło
12
+1 Zauważ, że dotyczy to nawet tablic! patrz stackoverflow.com/questions/1450957/…
bobince
1
@bobince: Wewnętrznie, jasne. Jednak logicznie rzecz biorąc , tablice mają „klucze” w postaci liczb całkowitych.
Wyścigi lekkości na orbicie
1
Pamiętaj, że użycie liczby całkowitej jako klucza zmieni długość twojej tablicy. Zamiast tego zdecydowanie powinieneś użyć Object. Chciałem tylko użyć identyfikatora facebooka jako klucza, a JSON.stringify zawiesiłby moją maszynę;)
Krystian
2
@LightnessRacesinOrbit Wewnętrzne szczegóły mogą jednak nadal wyciekać i gryźć. Zobacz tę uproszczoną wersję tego, na co natknąłem się dzisiaj: jsfiddle.net/cincodenada/pseujLex/2 Może wydawać się wymyślona po zmniejszeniu, ale była sensowną częścią większego skryptu (i jest nieco mniej wymyślona w CoffeeScript: jsfiddle.net/ cincodenada / oojr7Ltn / 2 ). Ten pozorny szczegół implementacji kosztował mnie dzisiaj sporo poszukiwań błędów.
cincodenada
1
Mała uwaga na liczby niecałkowite: 0.25i .25rozwiąż ten sam ciąg "0.25". Więc jeśli używasz klawiszy ułamkowych, można odzyskać własność numerycznie ustawionego klucza 0.25za pomocą 0.25, .25, "0.25"ale nie ".25".
Sandy Gifford
35

Możesz po prostu użyć obiektu:

var test = {}
test[2300] = 'Some string';
Annie
źródło
16
Nadal zostaje rzucony na ciąg.
drew010
1
@ drew010 tak, obiekty JavaScript pozwalają na indeksowanie tylko za pomocą łańcuchów.
Pithikos
22

Jak mówią ludzie, JavaScript zamieni ciąg liczbowy na liczbę całkowitą, więc nie jest możliwe użycie bezpośrednio na tablicy asocjacyjnej, ale obiekty będą działać dla ciebie w podobny sposób, jak myślę.

Możesz stworzyć swój obiekt:

var object = {};

I dodaj wartości tak, jak działa tablica:

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

To da ci:

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

Następnie możesz uzyskać do niego dostęp jak do tablicy w innych językach, uzyskując klucz:

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

Testowałem i działa.

Jesuslg123
źródło
17

Jeśli przypadek użycia przechowuje dane w kolekcji, wówczas ECMAScript 6 podaje Maptyp.

Inicjalizacja jest tylko trudniejsza.

Oto przykład:

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

Wynik:

=== With Map ===
1: One (number)
2: Two (number)
3: Three (number)
=== With Object ===
1: One (string)
2: Two (string)
3: Three (string)
Pragmateek
źródło
11

Kompilowanie innych odpowiedzi:

Obiekt

var test = {};

Gdy używasz liczby jako klucza nowej właściwości, liczba zamienia się w ciąg:

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

Podczas uzyskiwania dostępu do wartości właściwości przy użyciu tej samej liczby, liczba jest ponownie przekształcana w ciąg:

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

Jednak podczas pobierania kluczy z obiektu nie zostaną one zamienione z powrotem w liczby:

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

Mapa

ECMAScript 6 umożliwia wykorzystanie obiektu Map ( dokumentacja , porównanie z Object ). Jeśli Twój kod ma być interpretowany lokalnie lub tabela zgodności ECMAScript 6 wygląda na wystarczająco zieloną do Twoich celów, rozważ użycie mapy:

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

Żadna konwersja typu nie jest wykonywana, na lepsze i na gorsze:

console.log(test.get('2300'));
// Output: undefined
test.set('2300', 'Very different string');
console.log(test.get(2300));
// Output: 'Some string'
wordbug
źródło
4

Użyj obiektu zamiast tablicy. Tablice w JavaScript nie są tablicami asocjacyjnymi. Są to obiekty z magią związaną z dowolnymi właściwościami, których nazwy wyglądają jak liczby całkowite. Ta magia nie jest tym, czego chcesz, jeśli nie używasz ich jako tradycyjnej struktury przypominającej tablicę.

var test = {};
test[2300] = 'some string';
console.log(test);
bdukes
źródło
1
Mogą to być tablice asocjacyjne, ale tylko dlatego, że są również obiektami, które mogą mieć ustawione nazwane właściwości. Ale to po prostu sprawia, że ​​rzeczy są absurdalnie zagmatwane, więc tak, obiekty są znacznie lepsze w użyciu.
Graza
Tablice nigdy nie mogą być asocjacyjne Graza. Jeśli spróbujesz użyć kluczy w tablicy, a następnie przejrzysz je, zauważysz, że przechodzisz przez wszystkie domyślne metody i właściwości tablic -> niezbyt pożądane.
Swizec Teller
@Swizec - właśnie dlatego powiedziałem „absurdalnie zagmatwane”. Państwo może używać tablicy jako tablicy asocjacyjnej - czyli jako pary nazwa / wartość, ale nigdy nie będzie chciał ich iteracji! (Po prostu
Graza
tak, ale podczas iteracji nie są w żadnej określonej kolejności (tj. kolejność nie jest gwarantowana), co byłoby celem ich numerowania, więc jest to o wiele gorsze niż tylko mylenie.
Julix,
3

Spróbuj użyć obiektu, a nie tablicy:

var test = new Object(); test[2300] = 'Some string';
Jeff Hammerbacher
źródło
3
To jest zdecydowanie droga. W ten sposób nie utworzysz tablicy zawierającej 2300 wpisów w celu przechowywania pojedynczego ciągu.
Krystian
2
Tablice @Krystian JS to fałszywe tablice. Uruchom var a = []; a[Math.pow(2, 30)] = 'hello';i nie zobaczysz, że użycie przeglądarki / pamięci wzrośnie o ponad gigabajt, ale zobaczysz a.length1073741824. Maszyny wirtualne wyraźnie przechowują niektóre „tablice” przy użyciu innej struktury danych, zgaduję, że po prostu hashtable, przynajmniej jeśli są wystarczająco nieliczne.
Andy
2

Uzyskaj wartość dla właściwości tablicy asocjacyjnej, gdy nazwa właściwości jest liczbą całkowitą:

Zaczynając od tablicy asocjacyjnej, w której nazwy właściwości są liczbami całkowitymi:

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

Wypchnij elementy do tablicy:

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

Przejdź przez tablicę i zrób coś z wartością właściwości.

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

Wynik konsoli powinien wyglądać następująco:

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

Jak widać, można obejść ograniczenie tablicy asocjacyjnej i mieć nazwę właściwości będącą liczbą całkowitą.

UWAGA: Tablica asocjacyjna w moim przykładzie to zawartość JSON, którą miałbyś, gdybyś serializował obiekt Dictionary <string, string> [].

Jason Williams
źródło
0

Użyj obiektu - z liczbą całkowitą jako kluczem - zamiast tablicy.

Wyższy poziom
źródło
0

Czasami używam prefiksów dla moich kluczy. Na przykład:

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

obj = {};

obj[key] = val;

Teraz nie masz żadnego problemu z uzyskaniem do nich dostępu.

pictus
źródło