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?

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"]);

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';

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.


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)

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'

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

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';

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> [].



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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.