czy są słowniki w javascript, takie jak python?

103

Muszę zrobić słownik w javascript w ten sposób

nie pamiętam dokładnej notacji, ale było to coś takiego:

states_dictionary={ CT=[alex,harry], AK=[liza,alex], TX=[fred, harry] ........ }

czy jest coś takiego w javascript?

Alex Gordon
źródło
2
Zobacz to pytanie: stackoverflow.com/questions/130543/…
Manoj Govindan
5
Odpowiedź, którą zaakceptowałeś, jest bardzo zła.
Esben Skov Pedersen,
@EsbenSkovPedersen Jakie błędy zauważyłeś w tej odpowiedzi?
Anderson Green
Widzę, że jest edytowany po skomentowaniu. Wygląda na to, że brakowało
Esben Skov Pedersen
2
Przeczytaj najnowszą odpowiedź dla map ES6 stackoverflow.com/a/32993723/1993919 (komentując z tego samego powodu, co została opublikowana)
Old Badman Gray

Odpowiedzi:

132

To jest stary post, ale pomyślałem, że i tak powinienem podać ilustrowaną odpowiedź.

Użyj notacji obiektowej JavaScript. Tak jak to:

states_dictionary={ 
     "CT":["alex","harry"], 
     "AK":["liza","alex"], 
     "TX":["fred", "harry"]
};

Aby uzyskać dostęp do wartości:

states_dictionary.AK[0] //which is liza

lub możesz użyć notacji obiektu literału javascript, przy czym klucze nie wymagają cudzysłowów:

states_dictionary={ 
     CT:["alex","harry"], 
     AK:["liza","alex"], 
     TX:["fred", "harry"]
};
Szef
źródło
12
warto zauważyć, że pierwszy przykład powinien zawierać ten sam obiekt w obu językach przy użyciu dokładnie tej samej składni, z wyjątkiem zamykającego znaku „;”. States_dictionary = {"CT": ["alex", "harry"], "AK": ["liza", "alex"], "TX": ["fred", "harry"]}
Denis C
Jestem bardziej przyzwyczajony do dosłownej notacji obiektu, ponieważ uzyskujesz do nich dostęp w ten sam sposób, jaka jest różnica między nimi?
John Demetriou
2
@JohnDemetriou Główną różnicą jest to, że klucze notacji obiektu javascript muszą być ciągami znaków (w podwójnych cudzysłowach „”). Notacja obiektu jest taka, jak w JSON dla wymiany danych i została zainspirowana dosłowną notacją obiektu; warto zauważyć, że JSON jest zwykle używany w kontekście stringów
Chief
2
Właściwie Python dopuszcza średniki kończące instrukcję, więc pierwszy przykład jest całkowicie poprawny zarówno w Pythonie, jak i JavaScript
celticminstrel
Jeśli wartość pochodzi od użytkownika, a następnie ostrożność należy podjąć w celu zastosowania Object.hasOwnProperty.call(dictionary, key)(w przeciwnym razie użytkownik może wprowadzić wartość valueOf i dictionary['valueOf']zwraca Object.valueOf()funkcję należącej do prototypu obiektu, który nie jest chyba to, co Twój kod oczekiwałby - potencjalny błąd lub problem zabezpieczeń ). Jeśli klucz nie jest łańcuchem, należy zachować ostrożność, w przeciwnym razie niejawne konwersje liczbowe i toString spowodują problemy. Typ ES6 Mapzostał zaprojektowany w celu zapewnienia rozszerzonej funkcjonalności słowników.
robocat
54

Do 2015 r. Nie było żadnych rzeczywistych tablic asocjacyjnych w JavaScript (wersja ECMAScript 6). Od tego czasu możesz używać obiektu Map jako stanów Robocat. Sprawdź szczegóły w MDN . Przykład:

let map = new Map();
map.set('key', {'value1', 'value2'});
let values = map.get('key');

Bez wsparcia dla ES6 możesz spróbować użyć obiektów:

var x = new Object();
x["Key"] = "Value";

Jednak w przypadku obiektów nie jest możliwe użycie typowych właściwości tablic lub metod, takich jak array.length. Przynajmniej jest możliwy dostęp do „tablicy obiektów” w pętli for-in.

Alex
źródło
3
A co z występem? czy wyszukiwanie klucza w obiekcie jest ciągłe?
Saher Ahwal
5
Ponieważ o ["key"] jest odpowiednikiem o.key w Javascript, wydajność jest prawie taka sama. Jednak wydajność zależy od aparatu JavaScript / przeglądarki internetowej. Jest między nimi sporo różnic, zwłaszcza w starszych wersjach.
Alex
ECMAScript 6 definiuje oficjalny obiekt Map (tj. „Nie ma rzeczywistych tablic asocjacyjnych w Javascript” jest teraz niepoprawne).
robocat
18

Zdaję sobie sprawę, że to stare pytanie, ale wyskakuje w Google, gdy szukasz `` słowników javascript '', więc chciałbym dodać do powyższych odpowiedzi, że w ECMAScript 6 Mapzostał wprowadzony oficjalny obiekt, którym jest słownik realizacja:

var dict = new Map();
dict.set("foo", "bar");

//returns "bar"
dict.get("foo");

W przeciwieństwie do zwykłych obiektów javascript dopuszcza dowolny obiekt jako klucz:

var foo = {};
var bar = {};
var dict = new Map();
dict.set(foo, "Foo");
dict.set(bar, "Bar");

//returns "Bar"
dict.get(bar);

//returns "Foo"
dict.get(foo);

//returns undefined, as {} !== foo and {} !== bar
dict.get({});
JimmyMcHoover
źródło
U mnie działa, miło jest użyć czystszej metody ES6. Dziękuję Ci! Kontynuuj, czy znamy jakikolwiek sposób na "zbiorcze set ()", np. Jak python dict = { key: value)?
Joe Sadoski
10

Stworzyłem tutaj prosty słownik w JS:

function JSdict() {
    this.Keys = [];
    this.Values = [];
}

// Check if dictionary extensions aren't implemented yet.
// Returns value of a key
if (!JSdict.prototype.getVal) {
    JSdict.prototype.getVal = function (key) {
        if (key == null) {
            return "Key cannot be null";
        }
        for (var i = 0; i < this.Keys.length; i++) {
            if (this.Keys[i] == key) {
                return this.Values[i];
            }
        }
        return "Key not found!";
    }
}


// Check if dictionary extensions aren't implemented yet.
// Updates value of a key
if (!JSdict.prototype.update) {
    JSdict.prototype.update = function (key, val) {
        if (key == null || val == null) {
            return "Key or Value cannot be null";
        }
        // Verify dict integrity before each operation
        if (keysLength != valsLength) {
            return "Dictionary inconsistent. Keys length don't match values!";
        }
        var keysLength = this.Keys.length;
        var valsLength = this.Values.length;
        var flag = false;
        for (var i = 0; i < keysLength; i++) {
            if (this.Keys[i] == key) {
                this.Values[i] = val;
                flag = true;
                break;
            }
        }
        if (!flag) {
            return "Key does not exist";
        }
    }
}



// Check if dictionary extensions aren't implemented yet.
// Adds a unique key value pair
if (!JSdict.prototype.add) {
    JSdict.prototype.add = function (key, val) {
        // Allow only strings or numbers as keys
        if (typeof (key) == "number" || typeof (key) == "string") {
            if (key == null || val == null) {
                return "Key or Value cannot be null";
            }
            if (keysLength != valsLength) {
                return "Dictionary inconsistent. Keys length don't match values!";
            }
            var keysLength = this.Keys.length;
            var valsLength = this.Values.length;
            for (var i = 0; i < keysLength; i++) {
                if (this.Keys[i] == key) {
                    return "Duplicate keys not allowed!";
                }
            }
            this.Keys.push(key);
            this.Values.push(val);
        }
        else {
            return "Only number or string can be key!";
        }
    }
}

// Check if dictionary extensions aren't implemented yet.
// Removes a key value pair
if (!JSdict.prototype.remove) {
    JSdict.prototype.remove = function (key) {
        if (key == null) {
            return "Key cannot be null";
        }
        if (keysLength != valsLength) {
            return "Dictionary inconsistent. Keys length don't match values!";
        }
        var keysLength = this.Keys.length;
        var valsLength = this.Values.length;
        var flag = false;
        for (var i = 0; i < keysLength; i++) {
            if (this.Keys[i] == key) {
                this.Keys.shift(key);
                this.Values.shift(this.Values[i]);
                flag = true;
                break;
            }
        }
        if (!flag) {
            return "Key does not exist";
        }
    }
}

Powyższa implementacja może być teraz używana do symulacji słownika jako:

var dict = new JSdict();

dict.add(1, "one")

dict.add(1, "one more")
"Duplicate keys not allowed!"

dict.getVal(1)
"one"

dict.update(1, "onne")

dict.getVal(1)
"onne"

dict.remove(1)

dict.getVal(1)
"Key not found!"

To tylko podstawowa symulacja. Można go dodatkowo zoptymalizować, wdrażając lepszy algorytm czasu działania, aby działał przy co najmniej O (nlogn) złożoności czasowej lub nawet mniejszej. Podobnie jak scalanie / szybkie sortowanie na tablicach, a następnie wyszukiwanie w trybie B dla wyszukiwań. Nie spróbowałem ani nie szukałem informacji o mapowaniu funkcji skrótu w JS.

Ponadto klucz i wartość obiektu JSdict mogą zostać zamienione na zmienne prywatne, aby były podstępne.

Mam nadzieję że to pomoże!

EDYCJA >> Po zaimplementowaniu powyższego osobiście użyłem obiektów JS jako tablic asocjacyjnych, które są dostępne od razu po wyjęciu z pudełka.

Jednak chciałbym, aby szczególną wzmiankę o dwóch metod, które w rzeczywistości okazały się pomocne, aby to wygodny hashtable doświadczenie.

Viz: dict.hasOwnProperty (klucz) i usuń dict [klucz]

Przeczytaj ten post jako dobre źródło informacji na temat tego wdrożenia / użytkowania. Dynamiczne tworzenie kluczy w tablicy asocjacyjnej JavaScript

Dzięki!

Vaibhav
źródło
5

Użyj obiektów JavaScript. Możesz uzyskać dostęp do ich właściwości, takich jak klucze w słowniku. To jest podstawa JSON. Składnia jest podobna do słowników Pythona. Zobacz: JSON.org

Adam
źródło
4

Stare pytanie, ale ostatnio potrzebowałem zrobić port AS3> JS, a ze względu na szybkość napisałem prosty obiekt Dictionary w stylu AS3 dla JS:

http://jsfiddle.net/MickMalone1983/VEpFf/2/

Jeśli nie wiesz, słownik AS3 umożliwia użycie dowolnego obiektu jako klucza, a nie tylko łańcuchów. Przydają się, gdy już znajdziesz dla nich zastosowanie.

Nie jest tak szybki, jak byłby obiekt natywny, ale nie znalazłem z nim żadnych znaczących problemów w tym zakresie.

API:

//Constructor
var dict = new Dict(overwrite:Boolean);

//If overwrite, allows over-writing of duplicate keys,
//otherwise, will not add duplicate keys to dictionary.

dict.put(key, value);//Add a pair
dict.get(key);//Get value from key
dict.remove(key);//Remove pair by key
dict.clearAll(value);//Remove all pairs with this value
dict.iterate(function(key, value){//Send all pairs as arguments to this function:
    console.log(key+' is key for '+value);
});


dict.get(key);//Get value from key
MickMalone1983
źródło
1
Ładna i przydatna biblioteka! Dodałem funkcję get, której moim zdaniem brakowało i naprawiłem kilka drobnych problemów ze składnią (brak średnika itp.). Oto zmodyfikowane skrzypce: Dictionary in JSFiddle
Matt
Dobra robota, nie wiem, dlaczego tego tam nie było!
MickMalone1983
2

Firefox 13+ zapewnia eksperymentalną implementację mapobiektu podobnego do dictobiektu w Pythonie. Specyfikacje tutaj .

Jest dostępny tylko w przeglądarce Firefox, ale wygląda lepiej niż użycie atrybutów pliku new Object(). Cytat z dokumentacji:

  • Obiekt ma prototyp, więc na mapie znajdują się domyślne klucze. Można to jednak obejść za pomocą map = Object.create(null).
  • Klucze ObjectStrings, gdzie mogą mieć dowolną wartość Map.
  • Możesz łatwo uzyskać rozmiar, Mappodczas gdy musisz ręcznie śledzić rozmiar dla pliku Object.
mquandalle
źródło