Porównanie języków programowania (tablica asocjacyjna)
To porównanie języków programowania (tablice asocjacyjne) porównuje funkcje struktur danych tablic asocjacyjnych lub przetwarzania wyszukiwania tablic dla ponad 40 języków programowania komputerów .
Wsparcie językowe
Poniżej znajduje się porównanie tablic asocjacyjnych (także „mapowania”, „hash” i „słownika”) w różnych językach programowania.
awk
Awk ma wbudowaną obsługę tablic asocjacyjnych na poziomie języka.
Na przykład:
książka telefoniczna [ "Sally Smart" ] = "555-9999" książka telefoniczna [ "John Doe" ] = "555-1212" książka telefoniczna [ "J. Random Hacker" ] = "555-1337"
Poniższy kod przechodzi przez powiązaną tablicę i wyświetla jej zawartość:
for ( nazwisko w książce telefonicznej ) { drukuj nazwisko , "" , książka telefoniczna [ imię ] }
Użytkownik może wyszukiwać elementy w tablicy asocjacyjnej i usuwać elementy z tablicy.
Poniżej pokazano, w jaki sposób wielowymiarowe tablice asocjacyjne mogą być symulowane w standardowym Awk przy użyciu konkatenacji i wbudowanej zmiennej separatora łańcuchów SUBSEP:
{ # dla każdej linii wejściowej multi [ $ 1 SUBSEP $ 2 ] ++ ; } # KONIEC { for ( x in multi ) { split ( x , arr , SUBSEP ); print arr [ 1 ], arr [ 2 ], multi [ x ]; } }
C
Nie ma standardowej implementacji tablic asocjacyjnych w C , ale dostępna jest biblioteka innej firmy, C Hash Table, z licencją BSD.
Inna biblioteka innej firmy, uthash, również tworzy tablice asocjacyjne ze struktur C. Struktura reprezentuje wartość, a jedno z pól struktury służy jako klucz.
Wreszcie, biblioteka GLib obsługuje również tablice asocjacyjne wraz z wieloma innymi zaawansowanymi typami danych i jest zalecaną implementacją Projektu GNU.
Podobnie jak GLib , wieloplatformowa struktura Core Foundation firmy Apple udostępnia kilka podstawowych typów danych. W szczególności istnieją CFDictionary zliczane w referencjach i CFMutableDictionary.
C#
C# używa klas kolekcji dostarczonych przez .NET Framework . Najczęściej używanym typem tablicy asocjacyjnej jest System.Collections.Generic.Dictionary<TKey, TValue>
, który jest zaimplementowany jako zmienna tablica skrótów. Stosunkowo nowy System.Collections.Immutable
, dostępny w .NET Framework w wersji 4,5 i nowszych oraz we wszystkich wersjach .NET Core , zawiera również typ System.Collections.Immutable.Dictionary<TKey, TValue>
, który jest implementowany przy użyciu drzewo AVL . Metody, które normalnie zmutowałyby obiekt w miejscu, zamiast tego zwracają nowy obiekt, który reprezentuje stan oryginalnego obiektu po mutacji.
kreacja
Poniżej przedstawiono trzy sposoby wypełniania zmiennego słownika:
- metodę
Add
, która dodaje klucz i wartość oraz zgłasza wyjątek , jeśli klucz już istnieje w słowniku; - przypisanie do indeksatora, który nadpisuje dowolną istniejącą wartość, jeśli jest obecna; I
- przypisanie do właściwości zapasowej indeksatora, dla którego indeksatorem jest cukier składniowy (nie dotyczy C#, zobacz przykłady F# lub VB.NET ).
var słownik = nowy Słownik < string , string >(); słownik . Dodaj ( "Sally Smart" , "555-9999" ); słownik [ "John Doe" ] = "555-1212" ; // Niedozwolone w C#. // Dictionary.Item("J. Random Hacker") = "553-1337"; słownik [ "J. Random Hacker" ] = "553-1337" ;
Słownik można również zainicjować podczas konstruowania przy użyciu "inicjatora kolekcji", który kompiluje do powtarzających się wywołań Add
.
var słownik = nowy Słownik < string , string > { { "Sally Smart" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" } };
Dostęp na klucz
Wartości są pobierane przede wszystkim za pomocą indeksatora (który zgłasza wyjątek, jeśli klucz nie istnieje) i metody TryGetValue
, która ma parametr wyjściowy dla poszukiwanej wartości i zwracaną wartość logiczną wskazującą, czy klucz został znaleziony.
var sallyNumber = słownik [ "Sally Smart" ];
var sallyNumber = ( słownik . TryGetValue ( „Sally Smart” , out var wynik ) ? result : „n/a” ;
W tym przykładzie wartość sallyNumber
będzie teraz zawierać ciąg "555-9999"
.
Wyliczenie
Słownik może być postrzegany jako sekwencja kluczy, sekwencja wartości lub sekwencja par kluczy i wartości reprezentowana przez instancje typu KeyValuePair <TKey, TValue>
, chociaż nie ma gwarancji kolejności. W przypadku posortowanego słownika programista może wybrać użycie SortedDictionary<TKey, TValue>
lub użyć metody rozszerzenia .Sort
LINQ podczas wyliczania.
Poniżej przedstawiono wyliczanie przy użyciu pętli foreach :
// przejrzyj kolekcję i wyświetl każdy wpis. foreach ( KeyValuePair < string , string > kvp w słowniku ) { Console . WriteLine ( "Numer telefonu dla {0} to {1}" , kvp . Klucz , kvp . Wartość ); }
C++
C++ ma postać tablicy asocjacyjnej o nazwie std::map
(patrz Standardowa biblioteka szablonów#Kontenery ). Mapę książki telefonicznej można by utworzyć za pomocą następującego kodu w C++:
#include <mapa> #include <string> #include <utility> int main () { std :: map < std :: string , std :: string > phone_book ; książka_telefoniczna . wstaw ( std :: make_pair ( "Sally Smart" , "555-9999" )); książka_telefoniczna . wstaw ( std :: make_pair ( "John Doe" , "555-1212" )); książka_telefoniczna . wstaw ( std :: make_pair ( "J. Random Hacker" , "553-1337" )); }
Lub mniej wydajnie, ponieważ tworzy to tymczasowe wartości std::string :
#include <mapa> #include <string> int main () { std :: map < std :: string , std :: string > phone_book ; phone_book [ "Sally Smart" ] = "555-9999" ; phone_book [ "John Doe" ] = "555-1212" ; phone_book [ "J. Random Hacker" ] = "553-1337" ; }
Dzięki rozszerzeniu list inicjalizacyjnych w C++11 wpisy mogą być dodawane podczas konstruowania mapy, jak pokazano poniżej:
#include <mapa> #include <string> int main () { std :: map < std :: string , std :: string > phone_book { { "Sally Smart" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" } }; }
Możesz przeglądać listę za pomocą następującego kodu (C++03):
std :: map < std :: string , std :: string >:: iterator curr , end ; for ( kurs = książka_telefoniczna . początek (), koniec = książka_telefoniczna . koniec (); kurs ! = koniec ; ++ kurs ) std :: cout << kurs -> pierwszy << " = " << kurs -> drugi << std :: endl ;
To samo zadanie w C++11:
for ( const auto & curr : phone_book ) std :: cout << curr . pierwszy << " = " << bieżący . sekunda << std :: endl ;
Korzystanie z powiązania strukturalnego dostępnego w C++ 17 :
for ( const auto & [ nazwa , liczba ] : książka_telefoniczna ) { std :: cout << nazwa << " = " << liczba << std :: endl ; }
W C++ klasa std::map
jest szablonowana , co pozwala na różne typy danych kluczy i wartości dla różnych instancji map
. Dla danej instancji map
klucze muszą być tego samego typu podstawowego. To samo musi dotyczyć wszystkich wartości. Chociaż std::map
jest zwykle implementowane przy użyciu samobalansującego się drzewa wyszukiwania binarnego , C++11 definiuje drugą mapę o nazwie std::unordered_map
, która ma algorytmiczną charakterystykę tablicy skrótów. Jest to również popularne rozszerzenie standardowej biblioteki szablonów (STL), zwykle nazywane hash_map
, dostępne w takich implementacjach, jak SGI i STLPort.
CFML
Struktura w CFML jest odpowiednikiem tablicy asocjacyjnej:
dynamicKeyName = "John Doe" ; phoneBook = { "Sally Smart" = "555-9999" , " #dynamicKeyName# " = "555-4321" , "J. Random Hacker" = "555-1337" , UnknownComic = "???" }; writeOutput ( telefon.NieznanyKomiks ); // ??? writeDump ( książka telefoniczna ); // cała struktura
Kobra
Inicjowanie pustego słownika i dodawanie elementów w Cobra :
dic jako Słownik < Ciągu , Ciągu > = Słownik < Ciągu , Ciągu > ( ) dic . _ dodaj ( 'Sally Smart' , '555-9999' ) dic . dodaj ( 'John Doe' , '555-1212' ) dic . add ( 'J. Random Hacker' , '553-1337' ) assert dic [ 'Sally Smart' ] == '555-9999'
Alternatywnie słownik można zainicjować ze wszystkimi elementami podczas konstruowania:
dic = { 'Sally Smart' : '555-9999' , 'John Doe' : '555-1212' , 'J. Losowy haker” : „553-1337” }
Słownik można wyliczyć za pomocą pętli for, ale nie ma gwarantowanej kolejności:
for key val in dic print "Numer telefonu [klucza] to [val] "
D
D oferuje bezpośrednie wsparcie dla tablic asocjacyjnych w języku rdzenia; takie tablice są implementowane jako tablica mieszająca z drzewami binarnymi. Równoważnym przykładem byłoby:
0
int main () { ciąg [ ciąg ] książka_telefoniczna ; phone_book [ "Sally Smart" ] = "555-9999" ; phone_book [ "John Doe" ] = "555-1212" ; phone_book [ "J. Random Hacker" ] = "553-1337" ; powrót ; }
Klucze i wartości mogą być dowolnego typu, ale wszystkie klucze w tablicy asocjacyjnej muszą być tego samego typu i to samo dotyczy wartości zależnych.
Zapętlenie wszystkich właściwości i powiązanych wartości oraz wydrukowanie ich można zakodować w następujący sposób:
foreach ( klucz , wartość ; phone_book ) { writeln ( "Liczba dla " ~ klucz ~ ": " ~ wartość ); }
Właściwość można usunąć w następujący sposób:
książka_telefoniczna . usuń ( "Sally Smart" );
Delfy
Delphi obsługuje kilka standardowych kontenerów, w tym TDictionary<T>:
używa SysUtils , Generics . Kolekcje ; var Książka telefoniczna : TDictionary < string , string >; Wpis : TPara < string , string >; rozpocząć książkę telefoniczną := TDictionary < string , string >. Utwórz ; Książka telefoniczna . Dodaj ( 'Sally Smart' , '555-9999' ) ; Książka telefoniczna . Dodaj ( 'John Doe' , '555-1212' ) ; Książka telefoniczna . Add ( 'J. Random Hacker' , '553-1337' ) ; for Entry in PhoneBook do Writeln ( Format ( 'Numer dla %s: %s' , [ Entry . Key , Entry . Value ])) ; koniec .
Wersje Delphi wcześniejsze niż 2009 nie oferują bezpośredniej obsługi tablic asocjacyjnych. Jednak tablice asocjacyjne można symulować za pomocą klasy TStrings:
0
procedura TForm1 . Button1Click ( nadawca : TObject ) ; var DataField : TStrings ; ja : liczba całkowita ; rozpocząć DataField := TStringList . Utwórz ; Pole danych . Wartości [ 'Sally Smart' ] := '555-9999' ; Pole danych . Wartości [ 'John Doe' ] := '555-1212' ; Pole danych . Wartości [ J. Losowy haker' ] := '553-1337' ; // uzyskaj dostęp do wpisu i wyświetl go w oknie komunikatu ShowMessage ( DataField . Values [ 'Sally Smart' ]) ; // pętla przez tablicę asocjacyjną dla i := do DataField . Count - 1 do begin ShowMessage ( 'Liczba dla' + DataField . Nazwy [ i ] + ':' + DataField . ValueFromIndex [ i ]) ; koniec ; Pole danych . za darmo ; koniec ;
Erlang
Erlang oferuje wiele sposobów przedstawiania odwzorowań; trzy najpopularniejsze w bibliotece standardowej to listy kluczy, słowniki i mapy.
listy kluczy
Listy kluczy to listy krotek , gdzie pierwszym elementem każdej krotki jest klucz, a drugim wartość. Funkcje do operowania na listach klawiszy znajdują się w list
.
PhoneBook = [{ "Sally Smith" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" }].
Dostęp do elementu listy kluczy można uzyskać za pomocą funkcji lists:keyfind/3
:
{_, Phone } = lists : keyfind ( "Sally Smith" , 1 , PhoneBook ), io : format ( "Phone number: ~s~n " , [ Phone ]).
Słowniki
Słowniki są zaimplementowane w module dict
biblioteki standardowej. Nowy słownik jest tworzony za pomocą dict:new/0
, a nowe pary klucz/wartość są przechowywane za pomocą funkcji dict:store/3
:
PhoneBook1 = dict : new (), PhoneBook2 = dict : store ( "Sally Smith" , "555-9999" , Dict1 ), PhoneBook3 = dict : store ( "John Doe" , "555-1212" , Dict2 ), PhoneBook = dict : store ( "J. Random Hacker" , "553-1337" , Dict3 ).
Taka szeregowa inicjalizacja byłaby bardziej idiomatycznie reprezentowana w Erlangu z odpowiednią funkcją:
PhoneBook = dict : from_list ([{ "Sally Smith" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" }]).
Dostęp do słownika można uzyskać za pomocą funkcji dict:find/2
:
{ ok , Telefon } = dict : find ( "Sally Smith" , Książka telefoniczna ), io : format ( "Telefon: ~s~n " , [ Telefon ]).
W obu przypadkach kluczem może być dowolny termin Erlanga. Wariacje obejmują orddict
, implementujący uporządkowane słowniki oraz gb_trees
, implementujący ogólnie zrównoważone drzewa.
Mapy
Mapy zostały wprowadzone w OTP 17.0 i łączą w sobie zalety list klawiszy i słowników. Mapa jest zdefiniowana przy użyciu składni #{ K1 => V1, ... Kn => Vn }
:
PhoneBook = #{ "Sally Smith" => "555-9999" , "John Doe" => "555-1212" , "J. Random Hacker" => "553-1337" }.
Podstawowe funkcje do interakcji z mapami są dostępne w module maps
. Na przykład maps:find/2
zwraca wartość powiązaną z kluczem:
{ ok , Phone } = maps : find ( "Sally Smith" , PhoneBook ), io : format ( "Phone: ~s~n " , [ Phone ]).
W przeciwieństwie do słowników mapy można dopasowywać do wzorców:
#{ "Sally Smith" , Telefon } = PhoneBook , io : format ( "Telefon: ~s~n " , [ Telefon ]).
Erlang zapewnia również cukier składniowy do aktualizacji funkcjonalnych — tworzenie nowej mapy na podstawie istniejącej, ale ze zmodyfikowanymi wartościami lub dodatkowymi kluczami:
PhoneBook2 = PhoneBook #{ % operator `:=` aktualizuje wartość skojarzoną z istniejącym kluczem "J. Random Hacker" : = "355-7331" , % operator `=>` dodaje nową parę klucz-wartość, potencjalnie zastępowanie istniejącego „Alicja w krainie czarów” => „555-1865” }
F#
Mapa<'Klucz,'Wartość>
W czasie wykonywania F# udostępnia typ Collections.Map<'Key,'Value>
, który jest niezmiennym drzewem AVL .
kreacja
Poniższy przykład wywołuje Map
konstruktora, który działa na liście (rozdzielana średnikami sekwencja elementów ujęta w nawiasy kwadratowe) krotek (które w języku F# są rozdzielanymi przecinkami sekwencjami elementów).
niech liczby = [ "Sally Smart" , "555-9999" ; „Jan Doe” , „555-1212” ; "J. Random Hacker" , "555-1337" ] |> Mapa
Dostęp na klucz
Wartości można wyszukać za pomocą jednego z elementów członkowskich Map
, takiego jak jego indeksator lub właściwość Item (które zgłaszają
wyjątek , jeśli klucz nie istnieje) lub funkcja TryFind
, która zwraca typ opcji o wartości Some <result>
, w przypadku pomyślnego wyszukiwania lub None
w przypadku niepowodzenia. Dopasowywanie wzorców może być następnie użyte do wyodrębnienia surowej wartości z wyniku lub można ustawić wartość domyślną.
let sallyNumber = liczby .[ "Sally Smart" ] // lub let sallyNumber = liczby . Przedmiot ( "Sally Smart" )
niech sallyNumber = dopasuj liczby . TryFind ( „Sally Smart” ) za pomocą | Niektóre ( liczba ) -> liczba | Brak -> „nie dotyczy”
W obu powyższych przykładach wartość sallyNumber
zawierałaby ciąg znaków „555-9999”
.
Dictionary<'TKey,'TValue>
Ponieważ F# jest językiem .NET, ma również dostęp do funkcji .NET Framework , w tym System . Kolekcje . ogólny . Dictionary < ' TKey , ' TValue >
type (który jest zaimplementowany jako tablica skrótów ), który jest podstawowym typem tablicy asocjacyjnej używanym w językach C# i Visual Basic. Ten typ może być preferowany podczas pisania kodu, który ma działać z innymi językami w .NET Framework, lub gdy charakterystyka wydajności tabeli skrótów jest preferowana w porównaniu z drzewem AVL.
kreacja
Funkcja dict
umożliwia wygodne tworzenie słownika .NET, który nie jest przeznaczony do mutacji; akceptuje sekwencję krotek i zwraca niezmienny obiekt, który implementuje IDictionary<'TKey,'TValue>
.
niech liczby = [ "Sally Smart" , "555-9999" ; „Jan Doe” , „555-1212” ; "J. Random Hacker" , "555-1337" ] |> dict
Gdy potrzebny jest zmienny słownik, konstruktor System . Kolekcje . ogólny . Słownik < ' TKey , ' TValue >
można wywołać bezpośrednio. Zobacz przykład języka C# na tej stronie, aby uzyskać dodatkowe informacje.
niech liczby = System . Kolekcje . ogólny . Słownik < string , string > () liczby . Dodaj ( "Sally Smart" , "555-9999" ) liczby .[ "John Doe" ] <- "555-1212" liczby . Przedmiot ( "J. Random Hacker" ) <- "555-1337"
Dostęp na klucz
IDictionary
mają indeksator, który jest używany w taki sam sposób jak Map
, chociaż odpowiednikiem TryFind
jest TryGetValue
, który ma parametr wyjściowy dla poszukiwanej wartości i zwracaną wartość logiczną wskazującą, czy klucz został znaleziony.
niech sallyNumber = niech zmienny wynik = "" jeśli liczby . TryGetValue ( "Sally Smart" i wynik ) , a następnie wynik inny "nie dotyczy"
F# umożliwia również wywoływanie funkcji tak, jakby nie miała ona parametru wyjściowego, a zamiast tego zwracała krotkę zawierającą jej regularną wartość zwracaną oraz wartość przypisaną do parametru wyjściowego:
niech sallyNumber = dopasuj liczby . TryGetValue ( "Sally Smart" ) za pomocą | prawda , liczba -> liczba | _ -> "nie dotyczy"
Wyliczenie
Słownik lub mapę można wyliczyć przy użyciu Seq.map
.
// przejrzyj kolekcję i wyświetl każdy wpis. numery |> Nast . map ( fun kvp -> printfn "Numer telefonu dla %O to %O" kvp . Klucz kvp . Wartość )
FoxPro
Visual FoxPro implementuje mapowanie z klasą kolekcji.
mapping = NEWOBJECT ( "Collection" ) mapowanie .Add ( "Żonkile" , "kwiat2" ) && Add(obiekt, klucz) – klucz musi być znakiem index = mapping .GetKey ( "kwiat2" ) && zwraca wartość indeksu 1 obiekt = mapping( "kwiat2" ) && zwraca "Żonkile" (pobierz według klucza) object = mapping(1) && zwraca "Żonkile" (pobierz według indeksu)
GetKey zwraca 0, jeśli klucz nie zostanie znaleziony.
Iść
Go ma wbudowaną obsługę tablic asocjacyjnych na poziomie języka, zwanych „mapami”. Typ klucza mapy może być tylko typu logicznego, numerycznego, łańcuchowego, tablicowego, struktury, wskaźnika, interfejsu lub kanału.
Typ mapy jest zapisywany: map[typ klucza]typwartości
Dodawanie elementów pojedynczo:
phone_book := make ( map [ string ] string ) // utwórz pustą mapę phone_book [ "Sally Smart" ] = "555-9999" phone_book [ "John Doe" ] = "555-1212" phone_book [ "J. Random Hacker " ] = "553-1337"
Literał mapy:
phone_book := map [ string ] string { "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Random Hacker" : "553-1337" , }
Iteracja po mapie:
// nad kluczami i wartościami klucza , wartość : = range phone_book { fmt . Printf ( "Liczba dla %s: %s\n" , klucz , wartość ) } // tylko dla klawiszy dla klucza := range phone_book { fmt . Printf ( "Nazwa: %s\n" , klucz ) }
Haskella
Język programowania Haskell udostępnia tylko jeden rodzaj kontenera asocjacyjnego – listę par:
m = [( "Sally Smart" , "555-9999" ), ( "John Doe" , "555-1212" ), ( "J. Random Hacker" , "553-1337" )] main = print ( lookup " John Doe" m )
wyjście:
Po prostu „555-1212”
Zwróć uwagę, że funkcja wyszukiwania zwraca wartość „Może”, czyli „Nic”, jeśli nie została znaleziona, lub „Tylko„ wynik ” ”, jeśli została znaleziona.
GHC , najczęściej używana implementacja Haskella, zapewnia dwa dodatkowe typy kontenerów asocjacyjnych. Inne implementacje również mogą je zapewniać.
Jednym z nich są polimorficzne mapy funkcjonalne (reprezentowane jako niezmienne zrównoważone drzewa binarne):
zaimportuj kwalifikowaną Data.Map jako M
m = M . włóż "Sally Smart" "555-9999" M . puste m' = M . wstaw "John Doe" "555-1212" m m'' = M . wstaw "J. Random Hacker" "553-1337" m' main = print ( M . lookup "John Doe" m'' :: Maybe String )
wyjście:
Po prostu „555-1212”
Wyspecjalizowana wersja dla kluczy całkowitych istnieje również jako Data.IntMap.
Wreszcie polimorficzna tablica mieszająca:
zaimportuj kwalifikowaną Data.HashTable jako H main = do m <- H . nowy ( == ) H . hashString H. _ wstaw m "Sally Smart" "555-9999" H . wstaw m "John Doe" "555-1212" H . wstaw m "J. Random Hacker" "553-1337" foo <- H . wyszukiwanie m „John Doe” print foo
wyjście:
Po prostu „555-1212”
Zarówno listy par, jak i mapy funkcjonalne zapewniają czysto funkcjonalny interfejs, który jest bardziej idiomatyczny w Haskell. W przeciwieństwie do tego, tablice skrótów zapewniają imperatywny interfejs w monadzie IO .
Jawa
W Javie tablice asocjacyjne są implementowane jako „mapy”, które są częścią struktury kolekcji Java . Od czasu J2SE 5.0 i wprowadzenia typów generycznych do Javy kolekcje mogą mieć określony typ; na przykład tablica asocjacyjna, która odwzorowuje ciągi na ciągi, może być określona w następujący sposób:
Mapa < String , String > phoneBook = nowy HashMap < String , String > (); książka telefoniczna . put ( "Sally Smart" , "555-9999" ); książka telefoniczna . put ( "John Doe" , "555-1212" ); książka telefoniczna . put ( "J. Random Hacker" , "555-1337" );
Metoda get
służy do uzyskiwania dostępu do klucza; na przykład wartość wyrażenia phoneBook.get("Sally Smart")
to "555-9999"
. Ten kod używa mapy skrótów do przechowywania tablicy asocjacyjnej, wywołując konstruktora klasy HashMap
. Ponieważ jednak kod używa tylko metod wspólnych dla interfejsu Map
, można użyć samobalansującego się drzewa binarnego przez wywołanie konstruktora klasy TreeMap
(który implementuje podinterfejs SortedMap
), bez zmiany definicji zmiennej phoneBook
lub reszty kodu lub przy użyciu innych bazowych struktur danych, które implementują interfejs Map
.
Funkcja skrótu w Javie, używana przez HashMap i HashSet, jest dostarczana przez metodę Object.hashCode()
. Ponieważ każda klasa w Javie dziedziczy po Object
, każdy obiekt ma funkcję mieszającą. Klasa może zastąpić domyślną implementację funkcji hashCode()
, aby zapewnić niestandardową funkcję skrótu bardziej zgodną z właściwościami obiektu.
Object zawiera również metodę equals(Object)
, która sprawdza równość obiektu z innym obiektem .
Haszowane struktury danych w Javie opierają się na obiektach utrzymujących następującą umowę między ich metodami hashCode()
i equals() :
Dla dwóch obiektów a i b ,
za . równa się ( b ) == b . równa się ( a ) jeśli a . równa się ( b ), wtedy a . hashCode () == b . kod hash ()
Aby zachować ten kontrakt, klasa, która przesłania equals()
musi również przesłaniać hashCode()
i odwrotnie, tak aby hashCode()
była oparta na tych samych właściwościach (lub podzbiorze właściwości) co equals()
.
Kolejną umową, jaką zaszyfrowana struktura danych ma z obiektem, jest to, że wyniki metod hashCode()
i equals()
nie ulegną zmianie po wstawieniu obiektu do mapy. Z tego powodu ogólnie dobrą praktyką jest opieranie funkcji skrótu na niezmiennych właściwościach obiektu.
Analogicznie, TreeMap i inne posortowane struktury danych wymagają zdefiniowania kolejności dla typu danych. Albo typ danych musi już mieć zdefiniowaną własną kolejność, poprzez implementację Comparable
; lub niestandardowy komparator
musi być dostarczony w momencie konstruowania mapy. Podobnie jak w przypadku HashMap powyżej, względna kolejność kluczy w TreeMap nie powinna się zmieniać po wstawieniu ich do mapy.
JavaScript
JavaScript (i jego ustandaryzowana wersja, ECMAScript ) to zorientowany obiektowo język oparty na prototypach .
Mapa i SłabaMapa
Współczesny JavaScript obsługuje tablice asocjacyjne przy użyciu klas Map
i WeakMap
. Mapa domyślnie nie zawiera żadnych kluczy; zawiera tylko to, co jest w nim wyraźnie umieszczone. Klucze i wartości mogą być dowolnego typu (w tym funkcje, obiekty lub dowolne prymitywy).
kreacja
Mapę można zainicjować wszystkimi elementami podczas budowy:
const phoneBook = nowa mapa ([ [ "Sally Smart" , "555-9999" ], [ "John Doe" , "555-1212" ], [ "J. Random Hacker" , "553-1337" ], ]) ;
Alternatywnie możesz zainicjować pustą mapę, a następnie dodać elementy:
const książka telefoniczna = nowa mapa (); książka telefoniczna . zestaw ( "Sally Smart" , "555-9999" ); książka telefoniczna . zestaw ( "John Doe" , "555-1212" ); książka telefoniczna . zestaw ( "J. Random Hacker" , "553-1337" );
Dostęp na klucz
Dostęp do elementu mapy można uzyskać za pomocą metody get
:
const sallyNumber = książka telefoniczna . get ( "Sally Smart" );
W tym przykładzie wartość sallyNumber
będzie teraz zawierać ciąg znaków „555-9999”.
Wyliczenie
Klucze na mapie są uporządkowane. Zatem podczas iteracji obiekt mapy zwraca klucze w kolejności ich wstawiania. Poniżej przedstawiono wyliczanie przy użyciu pętli for:
// przejrzyj kolekcję i wyświetl każdy wpis. for ( const [ nazwa , numer ] książki telefonicznej ) { console . log ( `Numer telefonu dla ${ name } to ${ number } ` ); }
Klucz można usunąć w następujący sposób:
książka telefoniczna . usuń ( "Sally Smart" );
Obiekt
Obiekt jest podobny do mapy — oba pozwalają ustawiać klucze na wartości, pobierać te wartości, usuwać klucze i wykrywać, czy wartość jest przechowywana w kluczu. Z tego powodu (i ponieważ nie było wbudowanych alternatyw) obiekty były historycznie używane jako mapy.
Istnieją jednak istotne różnice, które sprawiają, że w niektórych przypadkach preferowana jest mapa. W języku JavaScript obiekt jest odwzorowaniem nazw właściwości na wartości — czyli tablicą asocjacyjną z jednym zastrzeżeniem: klucze obiektu muszą być łańcuchem znaków lub symbolem (obiekty natywne i prymitywy niejawnie przekonwertowane na klucze łańcuchowe są dozwolone) . Obiekty zawierają również jedną cechę niezwiązaną z tablicami asocjacyjnymi: obiekt ma prototyp, więc zawiera klucze domyślne, które mogą wchodzić w konflikt z kluczami zdefiniowanymi przez użytkownika. Tak więc wyszukiwanie właściwości skieruje wyszukiwanie do definicji prototypu, jeśli obiekt nie definiuje właściwości.
Literał obiektowy jest zapisywany jako { właściwość1: wartość1, właściwość2: wartość2, ... }
. Na przykład:
const myObject = { „Sally Smart” : „555-9999” , „John Doe” : „555-1212” , „J. Random Hacker” : „553-1337” , };
Aby uniemożliwić wyszukiwaniu użycie właściwości prototypu, możesz użyć funkcji Object.setPrototypeOf
:
Obiekt . setPrototypeOf ( mójObiekt , null );
Począwszy od ECMAScript 5 (ES5), prototyp można również ominąć, używając Object.create(null)
:
const mójObiekt = Obiekt . utwórz ( null ); Obiekt . assign ( myObject , { "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Random Hacker" : "553-1337" , });
Jeśli nazwa właściwości jest prawidłowym identyfikatorem, cudzysłowy można pominąć, np.:
const myOtherObject = { foo : 42 , bar : false };
Wyszukiwanie jest zapisywane przy użyciu notacji dostępu do właściwości, albo nawiasów kwadratowych, które zawsze działają, albo notacji kropkowej, która działa tylko w przypadku kluczy identyfikacyjnych:
mójObiekt [ "John Doe" ] mójInnyObiekt . bla
Możesz także przejść przez wszystkie wyliczalne właściwości i powiązane wartości w pętli w następujący sposób (pętla for-in):
for ( właściwość const w myObiekt ) { const value = myObiekt [ właściwość ]; konsola . log ( `mójObiekt[ ${ właściwość } ] = ${ wartość } ` ); }
Lub (pętla for-of):
for ( const [ właściwość , wartość ] obiektu . wpisy ( mójObiekt ) ) { console . log ( ` ${ właściwość } = ${ wartość } ` ); }
Właściwość można usunąć w następujący sposób:
usuń mójObiekt [ "Sally Smart" ];
Jak wspomniano wcześniej, właściwościami są ciągi znaków i symbole. Ponieważ każdy natywny obiekt i prymityw można niejawnie przekonwertować na łańcuch, możesz:
myObject [ 1 ] // klucz to „1”; zauważ, że mójObiekt[1] == mójObiekt["1"] mójObiekt [[ "a" , "b" ]] // kluczem jest "a,b" mójObiekt [{ toString () { return "hello world" ; } }] // kluczem jest „witaj świecie”
We współczesnym JavaScript używanie typu Array jako tablicy asocjacyjnej jest uważane za złą formę. Zgodnie z konsensusem najlepsze do tego celu są klasy Object type i Map
/ WeakMap
. Powodem tego jest to, że jeśli tablica zostanie rozszerzona za pomocą prototypu, a obiekt zostanie utrzymany w nienaruszonym stanie, pętle for i for-in będą działać zgodnie z oczekiwaniami na asocjacyjnych „tablicach”. Kwestia ta została wysunięta na pierwszy plan przez popularność frameworków JavaScript, które w dużym stopniu, a czasem bezkrytycznie, wykorzystują prototypy do rozszerzania wbudowanych typów JavaScript.
Więcej informacji na ten temat można znaleźć w artykule Dzień świadomości tablic JavaScript i prototypów obiektów .
Julia
W Julii następujące operacje zarządzają tablicami asocjacyjnymi.
Zadeklaruj słownik:
książka telefoniczna = Dict ( "Sally Smart" => "555-9999" , "John Doe" => "555-1212" , "J. Random Hacker" => "555-1337" )
Element dostępowy:
książka telefoniczna ["Sally Smart"]
Dodaj element:
książka telefoniczna ["Nowy kontakt"] = "555-2222"
Usuń element:
usuń!(książka telefoniczna, „Sally Smart”)
Uzyskaj klucze i wartości jako iterowalne :
klucze (książka telefoniczna) wartości (książka telefoniczna)
KornShell 93 i zgodne muszle
W KornShell 93 i zgodnych powłokach (ksh93, bash4...) z tablicami asocjacyjnymi można używać następujących operacji.
Definicja:
skład -A książka telefoniczna ; # ksh93 zadeklaruj -Książkę telefoniczną ; # bash4 phonebook =([ "Sally Smart" ]= "555-9999" [ "John Doe" ]= "555-1212" [ "[[J. Random Hacker]]" ]= "555-1337" ) ;
Dereferencja:
${ książka telefoniczna [ "John Doe" ] } ;
Seplenienie
Lisp został pierwotnie pomyślany jako język „przetwarzania LISt”, a jednym z jego najważniejszych typów danych jest lista powiązana, którą można traktować jako listę skojarzeń („alist”).
( ( "Sally Smart" . "555-9999" ) ( "John Doe" . "555-1212" ) ( "J. Random Hacker" . "553-1337" ))
Składnia (x . y)
jest używana do wskazania pary przeciwnej
. Klucze i wartości nie muszą być tego samego typu na liście. Lisp i Scheme zapewniają operatory, takie jak assoc,
do manipulowania alistami w sposób podobny do tablic asocjacyjnych.
Common Lisp istnieje zestaw operacji specyficznych dla obsługi list asocjacyjnych , z których każda działa nieniszcząco.
Do dodania wpisu wykorzystywana jest funkcja acons
, tworząca i zwracająca nową listę skojarzeń. Lista asocjacji w Common Lisp naśladuje stos, to znaczy jest zgodna z zasadą „ostatnie weszło, pierwsze wyszło” (LIFO), a zatem poprzedza nagłówek listy.
( let (( phone-book NIL )) ( setf phone-book ( acons "Sally Smart" "555-9999" phone-book )) ( setf phone-book ( acons "John Doe" "555-1212" phone-book ) )) ( setf phone-book ( acons "J. Random Hacker" "555-1337" phone-book )))
Funkcję tę można interpretować jako akomodację dla operacji przeciwnych
.
;; Efekt ;; (cons (cons KEY VALUE) ALIST) ;; jest równoważne ;; (acons LISTA KLUCZOWYCH WARTOŚCI) ( let (( phone-book ' (( "Sally Smart" . "555-9999" ) ( "John Doe" . "555-1212" )))) ( cons ( cons "J. Random Hacker" "555-1337" ) książka telefoniczna ))
Oczywiście destrukcyjna operacja wypychania
umożliwia również wstawianie wpisów do listy skojarzeń, przy czym wpis musi stanowić wadę typu klucz-wartość, aby zachować ważność odwzorowania.
( push ( cons "Dummy" "123-4567" ) książka telefoniczna )
Wyszukiwanie wpisu według jego klucza odbywa się za pomocą assoc
, który może być skonfigurowany dla predykatu testowego i kierunku, w szczególności przeszukiwanie listy asocjacji od końca do początku. Wynik, jeśli jest dodatni, zwraca cały wpis cons, a nie tylko jego wartość. Nieuzyskanie pasującego klucza prowadzi do zwrotu wartości NIL
.
( assoc "John Doe" książka telefoniczna :test #' string= )
dwa uogólnienia assoc
: assoc-if
oczekuje funkcji predykatu, która sprawdza klucz każdego wpisu, zwracając pierwszy wpis, dla którego predykat po wywołaniu generuje wartość różną od ZERO
. assoc-if-not
odwraca logikę, akceptując te same argumenty, ale zwraca pierwszy wpis generujący NIL
.
;; Znajdź pierwszy wpis, którego klucz jest równy „John Doe”. ( assoc-if #' ( lambda ( klucz ) ( string= klucz "John Doe" )) książka telefoniczna ) ;; Znajduje pierwszy wpis, którego kluczem nie jest ani „Sally Smart”, ani „John Doe” ( assoc-if-not #' ( lambda ( key ) ( Member key ' ( „Sally Smart” „John Doe” ) :test #' string= )) książka telefoniczna )
Proces odwrotny, wykrywanie wpisu na podstawie jego wartości, wykorzystuje rassoc
.
;; Znajdź pierwszy wpis o wartości „555-9999”. ;; Testujemy wartości ciągów wejściowych za pomocą predykatu „string=”. ( rassoc "555-9999" książka telefoniczna :test #' string= )
Odpowiednie uogólnienia rassoc-if
i rassoc-if-not
istnieją.
;; Znajduje pierwszy wpis, którego wartość to „555-9999”. ( rassoc-if #' ( lambda ( wartość ) ( string= wartość "555-9999" )) książka telefoniczna ) ;; Znajduje pierwszy wpis, którego wartością nie jest „555-9999”. ( rassoc-if-not #' ( lambda ( wartość ) ( string = wartość "555-9999" )) książka telefoniczna )
Wszystkie poprzednie funkcje wyszukiwania wpisów można zastąpić ogólnymi wariantami zorientowanymi na listy, takimi jak find
, find-if
, find-if-not
, a także odpowiednimi funkcjami, takimi jak pozycja
i jej pochodne.
;; Znajdź wpis z kluczem „John Doe” i wartością „555-1212”. ( find ( cons "John Doe" "555-1212" ) książka telefoniczna : test #' równy )
Usuwanie, które nie ma określonego odpowiednika, opiera się na obiektach listowych, w tym destrukcyjnych.
;; Utwórz i zwróć listę bez żadnego wpisu, której klucz jest równy „John Doe”. ( remove-if #' ( lambda ( wpis ) ( string= ( wpis w samochodzie ) "John Doe" )) książka telefoniczna )
Iteracja jest realizowana za pomocą dowolnej funkcji, która oczekuje listy.
;; Iteruj za pomocą „mapy”. ( map NIL #' ( lambda ( wpis ) ( destructuring-bind ( klucz . wartość ) wpis ( format T "~&~s => ~s" wartość klucza ))) książka telefoniczna ) ;; Iteruj przez „dolist”. ( dolist ( wpis książki telefonicznej ) ( destructuring-bind ( klucz . wartość ) wpis ( format T "~&~s => ~s" wartość klucza )))
Ponieważ są to ustrukturyzowane listy, operacje przetwarzania i przekształcania mogą być stosowane bez ograniczeń.
;; Zwróć wektor wartości „książki telefonicznej”. ( map 'vector #' cdr książka telefoniczna ) ;; Destruktywnie modyfikuj „książkę telefoniczną” za pomocą „map-in”. ( map-in phone-book #' ( lambda ( wpis ) ( destructuring-bind ( klucz . wartość ) wpis ( cons ( klucz odwrotny ) ( wartość odwrotna )))) książka telefoniczna )
Ze względu na swój liniowy charakter listy alist są używane w przypadku stosunkowo małych zestawów danych. Common Lisp obsługuje również typ danych tabeli skrótów , a dla Scheme są one zaimplementowane w SRFI 69. Tabele skrótów mają większy narzut niż alisty, ale zapewniają znacznie szybszy dostęp, gdy jest wiele elementów. Kolejną cechą charakterystyczną jest fakt, że tablice mieszające Common Lisp, w przeciwieństwie do list asocjacyjnych, nie zachowują kolejności wstawiania wpisów.
Wspólne tablice skrótów Lispa są konstruowane za pomocą funkcji make-hash-table
, której argumenty obejmują, między innymi, predykat do testowania klucza wejściowego. Tolerując dowolne obiekty, nawet heterogeniczność w ramach pojedynczej instancji tablicy skrótów, specyfikacja tej funkcji key :test
jest ograniczona do rozróżnialnych jednostek: standard Common Lisp nakazuje jedynie obsługę eq
, eql
, equal
i equalp
, ale wyznacza dodatkowe lub operacje niestandardowe jako dopuszczalne dla konkretnych implementacji.
( let (( phone-book ( make-hash-table :test #' equal ))) ( setf ( gethash „Sally Smart” książka telefoniczna ) „555-9999” ) ( setf ( gethash „John Doe” książka telefoniczna ) "555-1212" ) ( setf ( gethash "J. Random Hacker" książka telefoniczna ) "553-1337" ))
Funkcja gethash
pozwala na uzyskanie wartości skojarzonej z kluczem.
( książka telefoniczna gethash „John Doe” )
Dodatkowo można określić wartość domyślną dla przypadku braku klucza.
( gethash „Incognito” książka telefoniczna „ brak-takiego-klucza ”)
Wywołanie gethash
faktycznie zwraca dwie wartości: wartość lub wartość zastępczą dla klucza i wskaźnik logiczny, zwracający T
, jeśli tablica mieszająca zawiera klucz i NIL
, aby zasygnalizować jego brak.
( powiązanie-wielowartościowe ( wartość zawiera-klucz ) ( gethash Książka telefoniczna „Sally Smart” ) ( jeśli zawiera-klucz ( format T „~&Powiązana wartość to: ~s” wartość ) ( format T „~&Klucz może nie można znaleźć." )))
Użyj remhash
do usunięcia wpisu powiązanego z kluczem.
( remhash książka telefoniczna „J. Random Hacker” )
clrhash
całkowicie opróżnia tablicę skrótów.
( książka telefoniczna clrhash )
Dedykowana funkcja maphash
specjalizuje się w iteracji tablic mieszających.
( maphash #' ( lambda ( wartość klucza ) ( format T "~&~s => ~s" wartość klucza )) książka telefoniczna )
Alternatywnie konstrukcja pętli
uwzględnia iteracje za pomocą kluczy, wartości lub połączeń obu.
;; Iteruj klucze i wartości tablicy skrótów. ( pętla dla klucza będącego haszem książki telefonicznej przy użyciu ( wartość skrótu ) do ( format T "~&~s => ~s" wartość klucza ) ) ;; Iteruj wartości tablicy skrótów. ( pętla dla wartości będącej wartościami mieszającymi książki telefonicznej do ( print value ))
Kolejna opcja wywołuje with-hash-table-iterator
, makro tworzące iterator, którego przetwarzanie ma być sterowane przez wywołującego.
( with-hash-table-iterator ( generator-wpisów -książka-telefoniczna ) ( pętla do ( wiązanie-wielowartościowe ( ma- wartość - klucza- wpisu ) ( generator wpisów ) ( jeśli ma-wpis ( format T "~&~s => wartość klucza ~s" ) ( zakończenie pętli )))))
Łatwo jest konstruować złożone abstrakcyjne typy danych w Lispie, używając struktur lub funkcji programowania zorientowanego obiektowo, w połączeniu z listami, tablicami i tablicami mieszającymi.
LPC
LPC implementuje tablice asocjacyjne jako podstawowy typ znany jako „mapa” lub „mapowanie”, w zależności od sterownika. Klucze i wartości mogą być dowolnego typu. Literał mapowania jest zapisywany jako ([ klucz_1 : wartość_1, klucz_2 : wartość_2 ])
. Kod proceduralny wygląda następująco:
mapowanie phone_book = ([]); phone_book [ "Sally Smart" ] = "555-9999" ; phone_book [ "John Doe" ] = "555-1212" ; phone_book [ "J. Random Hacker" ] = "555-1337" ;
Odwzorowania są dostępne do odczytu za pomocą operatora indeksowania w taki sam sposób, jak do zapisu, jak pokazano powyżej. Tak więc phone_book["Sally Smart"] zwróci ciąg "555-9999", a phone_book["Jan Kowalski"] zwróci 0. Testowanie obecności odbywa się za pomocą funkcji member(), np. if(member(phone_book, " Jan Kowalski")) write("Jan Kowalski jest wymieniony.\n");
Usuwanie odbywa się za pomocą funkcji zwanej m_delete() lub map_delete(), w zależności od sterownika: m_delete(phone_book, "Sally Smart");
Sterowniki LPC z rodziny Amylaar implementują odwzorowania wielowartościowe przy użyciu drugorzędnego indeksu numerycznego (inne sterowniki z rodziny MudOS nie obsługują odwzorowań wielowartościowych). Przykładowa składnia:
0
0
0
mapowanie phone_book = ([ : 2 ]); phone_book [ "Sally Smart" , ] = "555-9999" ; phone_book [ "Sally Smart" , 1 ] = "99 Sharp Way" ; phone_book [ "John Doe" , ] = "555-1212" ; phone_book [ "John Doe" , 1 ] = "3 Nigma Drive" ; phone_book [ "J. Random Hacker" , ] = "555-1337" ; phone_book [ "J. Random Hacker" , 1 ] = "77 Massachusetts Avenue" ;
Sterowniki LPC wystarczająco nowoczesne, aby obsługiwać konstrukcję foreach(), używają jej do iteracji przez swoje typy mapowania.
Lua
W Lua „tabela” jest podstawowym typem, który może być używany jako tablica (indeks numeryczny, szybki) lub jako tablica asocjacyjna.
Klucze i wartości mogą być dowolnego typu, z wyjątkiem nil. Poniżej skupiono się na indeksach nieliczbowych.
Literał tabeli jest zapisywany jako { wartość, klucz = wartość, [indeks] = wartość, ["ciąg bez identyfikatora"] = wartość }
. Na przykład:
phone_book = { [ "Sally Smart" ] = "555-9999" , [ "John Doe" ] = "555-1212" , [ "J. Random Hacker" ] = "553-1337" , -- Końcowy przecinek jest OK } aTable = { -- Tabela jako wartość subTable = { 5 , 7.5 , k = true }, -- klucz to "subTable" -- Funkcja jako wartość [ 'John Doe' ] = funkcja ( wiek ) jeśli wiek < 18 , to wróć „Młody”, w przeciwnym razie zwróć „Stary!” end end , -- Tabela i funkcja (oraz inne typy) mogą być również używane jako klucze }
Jeśli klucz jest prawidłowym identyfikatorem (nie zastrzeżonym słowem), cudzysłowy można pominąć. W identyfikatorach rozróżniana jest wielkość liter.
Wyszukiwanie jest zapisywane przy użyciu nawiasów kwadratowych, które zawsze działają, lub notacji kropkowej, która działa tylko w przypadku kluczy identyfikacyjnych:
print ( aTabela [ "John Doe" ]( 45 )) x = aTabela . podtabela . k
Możesz także przechodzić przez wszystkie klucze i powiązane wartości za pomocą iteratorów lub pętli for:
0
simple = { [ prawda ] = 1 , [ fałsz ] = , [ 3.14 ] = math.pi , x = 'x' , [ "!" ] = 42 } function FormatElement ( klucz , wartość ) return "[" .. tostring ( klucz ) .. "] = " .. wartość .. ", " koniec -- Iteracja po wszystkich kluczach tabeli . foreach ( simple , function ( k , v ) io.write ( FormatElement ( k , v )) end ) print "" for k , v w parach ( simple ) do io.write ( FormatElement ( k , v )) end print " " k = nil powtórz k , v = następny ( prosty , k ) if k ~= nil then io.write ( FormatElement ( k , v )) koniec do k == nil print ""
Wpis można usunąć, ustawiając go na nil:
prosty . x = zero
Podobnie możesz nadpisać wartości lub dodać je:
prosty [ '%' ] = "procent" prosty [ '!' ] = 111
Matematyka i język Wolframa
Mathematica i Wolfram Language używają wyrażenia asocjacyjnego do reprezentowania tablic asocjacyjnych.
książka telefoniczna = <| "Sally Smart" -> "555-9999" , "John Doe" -> "555-1212" , "J. Random Hacker" -> "553-1337" |> ;
Mieć dostęp:
książka telefoniczna [[ Klawisz [ "Sally Smart" ]]]
Jeśli klucze są ciągami znaków, słowo kluczowe Key nie jest konieczne, więc:
książka telefoniczna [[ "Sally Smart" ]]
Aby wyświetlić listę kluczy: i wartości
Klawisze [książka telefoniczna] Wartości [książka telefoniczna]
ŚWINKA
W MUMPS każda tablica jest tablicą asocjacyjną. Wbudowana, bezpośrednia obsługa tablic asocjacyjnych na poziomie języka dotyczy prywatnych, specyficznych dla procesu tablic przechowywanych w pamięci, zwanych „lokalnymi”, jak również stałych, współdzielonych, globalnych tablic przechowywanych na dysku, które są dostępne jednocześnie dla wielu zadań . Nazwa zmiennych globalnych jest poprzedzona daszkiem „^”, aby odróżnić je od zmiennych lokalnych.
SET ^książka telefoniczna("Sally Smart")="555-9999" ;; przechowywanie danych na stałe SET phonebook("John Doe")="555-1212" ;; przechowywanie danych tymczasowych SET phonebook("J. Random Hacker")="553-1337" ;; przechowywanie danych tymczasowych MERGE ^phonebook=phonebook ;; kopiowanie danych tymczasowych do danych stałych
Dostęp do wartości elementu wymaga po prostu użycia nazwy z indeksem dolnym:
NAPISZ "Numer telefonu :",^książka telefoniczna("Sally Smart"),!
Możesz także przejść przez powiązaną tablicę w następujący sposób:
SET NAME="" FOR S NAME=$ORDER(^telefon(NAME)) QUIT:NAME="" WRITE NAME," Phone Number :",^phonebook(NAME),!
Cel-C (Cocoa/GNUstep)
Cocoa i GNUstep , napisane w Objective-C , obsługują tablice asocjacyjne przy użyciu klastra NSMutableDictionary
(mutowalna wersja NSDictionary ).
Ta klasa umożliwia przypisania między dowolnymi dwoma obiektami. Kopia obiektu klucza jest wykonywana przed wstawieniem go do NSMutableDictionary
, dlatego klucze muszą być zgodne z protokołem NSCopying
. Podczas wstawiania do słownika obiekt wartości otrzymuje komunikat zatrzymania, aby zwiększyć liczbę odwołań. Obiekt wartości otrzyma komunikat zwalniający, gdy zostanie usunięty ze słownika (jawnie lub poprzez dodanie do słownika innego obiektu z tym samym kluczem).
NSMutableDictionary * aDictionary = [[ NSMutableDictionary alloc ] init ]; [ aZestaw słownikówObiekt : @"555-9999" forKey : @"Sally Smart" ]; [ aZestaw słownikówObiekt : @"555-1212" forKey : @"John Doe" ]; [ aZestaw słownikówObiekt : @"553-1337" forKey : @"Random Hacker" ];
Aby uzyskać dostęp do przypisanych obiektów, można użyć tego polecenia:
id anObject = [ aDictionary objectForKey : @"Sally Smart" ];
Wszystkie klucze lub wartości można wyliczyć za pomocą NSEnumerator
:
NSEnumerator * keyEnumerator = [ aSłownik keyEnumerator ]; klucz identyfikacyjny ; while (( key = [ keyEnumerator nextObject ])) { // ... przetwórz tutaj ... }
W systemach Mac OS X 10.5+ i iPhone OS klucze słowników można wyliczać bardziej zwięźle za pomocą konstrukcji NSFastEnumeration
:
for ( id key in aDictionary ) { // ... przetwórz tutaj ... }
Co jest jeszcze bardziej praktyczne, ustrukturyzowane wykresy danych można łatwo tworzyć za pomocą Cocoa , zwłaszcza NSDictionary
( NSMutableDictionary
). Można to zilustrować tym zwięzłym przykładem:
NSDictionary * aDictionary = [ NSDictionary DictionaryWithObjectsAndKeys : [ NSDictionary DictionaryWithObjectsAndKeys : @"555-9999" , @"Sally Smart" , @"555-1212" , @"John Doe" , nil ], @"students" , [ NSDictionary DictionaryWithObjectsAndKeys : @"553-1337" , @"Losowy haker" , zero ], @"hakerzy" , zero ];
Dostęp do odpowiednich pól można szybko uzyskać za pomocą kluczowych ścieżek:
id anObject = [ aDictionary valueForKeyPath : @"students.Sally Smart" ];
OCaml
Język programowania OCaml udostępnia trzy różne kontenery asocjacyjne. Najprostsza to lista par:
# niech m = [ "Sally Smart" , "555-9999" ; „Jan Doe” , „555-1212” ; "J. Random Hacker" , "553-1337" ];; val m : ( string * string ) list = [ ( "Sally Smart" , "555-9999" ); ( "John Doe" , "555-1212" ); ( "J. Random Hacker" , "553-1337" ) ] # Lista . assoc "John Doe" m ;; - : ciąg = "555-1212"
Drugi to polimorficzna tablica skrótów:
# niech m = Hashtbl . utwórz 3 ;; val m : ( ' _ a , ' _ b ) Hashtbl . t = < absstr > # Hashtbl . dodaj m "Sally Smart" "555-9999" ; Hashtbl . dodaj m "John Doe" "555-1212" ; Hashtbl . dodaj m "J. Random Hacker" "553-1337" ;; - : jednostka = () # Hashtbl . znajdź m "John Doe" ;; - : ciąg znaków = "555-1212"
Powyższy kod używa domyślnej funkcji skrótu OCaml Hashtbl.hash
, która jest definiowana automatycznie dla wszystkich typów. Aby użyć zmodyfikowanej funkcji skrótu, użyj interfejsu funktora Hashtbl.Make
do utworzenia modułu, takiego jak Map
.
Wreszcie mapy funkcjonalne (reprezentowane jako niezmienne zrównoważone drzewa binarne):
# moduł StringMap = Mapa . Utwórz ( ciąg znaków );; ... # niech m = StringMap . dodaj „Sally Smart” „555-9999” StringMap . puste niech m = StringMap . dodaj „John Doe” „555-1212” m niech m = StringMap . dodaj "J. Random Hacker" "553-1337" m ;; val m : ciąg StringMap . t = < absstr > # StringMap . znajdź "John Doe" m ;; - : ciąg znaków = "555-1212"
Zauważ, że aby skorzystać z Map
, musisz wyposażyć funktor Map.Make
w moduł definiujący typ klucza oraz funkcję porównania. Biblioteka innej firmy ExtLib zapewnia polimorficzną wersję map funkcjonalnych, zwaną PMap
, która po utworzeniu otrzymuje funkcję porównania.
Zarówno listy par, jak i mapy funkcjonalne zapewniają czysto funkcjonalny interfejs. Natomiast tablice skrótów zapewniają imperatywny interfejs. W przypadku wielu operacji tablice skrótów są znacznie szybsze niż listy par i mapy funkcyjne.
Optim J
Język programowania OptimJ jest rozszerzeniem języka Java 5. Podobnie jak Java, Optimj zapewnia mapy; ale OptimJ zapewnia również prawdziwe tablice asocjacyjne. Tablice Java są indeksowane nieujemnymi liczbami całkowitymi; tablice asocjacyjne są indeksowane dowolnym typem klucza.
String [ String ] phoneBook = { "Sally Smart" -> "555-9999" , "John Doe" -> "555-1212" , "J. Random Hacker" -> "553-1337" }; // String[String] nie jest typem java, ale typem optimj: // asocjacyjna tablica napisów indeksowana przez stringi. // iteracja po wartościach dla ( String number : phoneBook ) { System . na zewnątrz println ( liczba ); } // Poprzednia instrukcja drukuje: "555-9999" "555-1212" "553-1337" // iteracja po kluczach for ( String name : phoneBook . keys ) { System . na zewnątrz println ( nazwa + " -> " + phoneBook [ nazwa ] ); } // phoneBook[nazwa] dostęp do wartości za pomocą klucza (wygląda jak dostęp do tablicy java) // np. phoneBook["John Doe"] zwraca "555-1212"
Oczywiście można definiować tablice wielowymiarowe, mieszać tablice Java i tablice asocjacyjne, mieszać mapy i tablice asocjacyjne.
int [ Ciąg ][][ podwójny ] a ; Jawa . utylizacja _ Mapa < String [ Obiekt ] , Liczba całkowita > b ;
Perl 5
Perl 5 ma wbudowaną obsługę tablic asocjacyjnych na poziomie języka. Współczesny Perl odnosi się do tablic asocjacyjnych jako skrótów ; termin tablica asocjacyjna występuje w starszej dokumentacji, ale jest uważany za nieco archaiczny. Skróty Perla 5 są płaskie: klucze to ciągi znaków, a wartości to skalary. Jednak wartości mogą być odniesieniami do tablic lub innych skrótów, a standardowy moduł Perla 5 Tie::RefHash umożliwia używanie skrótów z kluczami referencyjnymi.
Zmienna mieszająca jest oznaczona symbolem % ,
aby odróżnić ją od skalarnych, tablicowych i innych typów danych. Literał skrótu to lista klucz-wartość, z preferowaną formą wykorzystującą token Perla =>
, który jest semantycznie w większości identyczny z przecinkiem i sprawia, że powiązanie klucz-wartość jest wyraźniejsze:
my %phone_book = ( 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '553-1337' , );
Dostęp do elementu hash wykorzystuje składnię $hash_name{$key}
– klucz jest otoczony nawiasami klamrowymi , a nazwa skrótu jest poprzedzona znakiem $
, co wskazuje, że sam element hash jest wartością skalarną, mimo że jest częścią skrótu . Wartość $phone_book{'John Doe'}
to '555-1212'
. % sigil jest używany tylko w odniesieniu do skrótu jako całości, na przykład podczas pytania o klucze
%phone_book
.
Listę kluczy i wartości można wyodrębnić odpowiednio za pomocą wbudowanych funkcji klucze
i wartości
. Na przykład, aby wydrukować wszystkie klucze skrótu:
foreach $nazwa ( klucze %telefon_książka ) { print $nazwa , "\n" ; }
Można iterować po parach (klucz, wartość) za pomocą każdej
funkcji:
while (( $nazwa , $liczba ) = each %telefon_book ) { print 'Numer dla ' , $nazwa , ': ' , $liczba , "\n" ; }
„Odniesienie” skrótu, które jest wartością skalarną wskazującą na skrót, jest określone w postaci dosłownej przy użyciu nawiasów klamrowych jako ograniczników, ze składnią podobną do określania literału skrótu:
my $phone_book = { 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Losowy haker' => '553-1337' , };
Dostęp do wartości w odwołaniu skrótu uzyskuje się za pomocą operatora dereferencji:
print $phone_book -> { 'Sally Smart' };
Gdy hash zawarty w odwołaniu do skrótu musi być określany jako całość, tak jak w przypadku funkcji kluczy
, składnia jest następująca:
foreach $name ( klucze % { $phone_book }) { print 'Numer dla ' , $ name , ': ' , $ phone_book -> { $ name }, "\n" ; }
Perl 6 (Raku)
Perl 6 , przemianowany na „Raku”, ma również wbudowaną obsługę tablic asocjacyjnych na poziomie języka, które są określane jako skróty lub obiekty pełniące rolę „asocjacyjną”. Podobnie jak w Perlu 5, domyślne skróty w Perlu 6 są płaskie: klucze to ciągi znaków, a wartości to skalary. Można zdefiniować skrót, aby nie wymuszał automatycznie wszystkich kluczy do łańcuchów: są one określane jako „skróty obiektowe”, ponieważ klucze takich skrótów pozostają oryginalnym obiektem, a nie jego ciągliwością.
Zmienna mieszająca jest zwykle oznaczana symbolem %
sigil , aby wizualnie odróżnić ją od skalarnych, tablicowych i innych typów danych oraz zdefiniować jej zachowanie wobec iteracji. Literał skrótu to lista klucz-wartość, z preferowaną formą wykorzystującą token Perla =>
, co sprawia, że powiązanie klucz-wartość jest bardziej przejrzyste:
my %phone-book = 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Losowy haker' => '553-1337' , ;
Dostęp do elementu hash wykorzystuje składnię %hash_name{$key}
– klucz jest otoczony nawiasami klamrowymi i nazwą hash (zauważ, że sigil nie zmienia się, w przeciwieństwie do Perla 5). Wartość %phone-book{'John Doe'}
to '555-1212'
.
Listę kluczy i wartości można wyodrębnić odpowiednio za pomocą wbudowanych funkcji klucze
i wartości
. Na przykład, aby wydrukować wszystkie klucze skrótu:
dla %książki telefonicznej . klucze -> $nazwa { powiedz $nazwa ; }
Domyślnie podczas iteracji przez hash uzyskuje się pary klucz-wartość.
for %phone-book -> $entry { powiedz "Numer for $entry.key(): $entry.value()" ; # przy użyciu rozszerzonych funkcji interpolacji }
Możliwe jest również uzyskanie naprzemiennych wartości kluczy i wartości wartości za pomocą metody kv
:
dla %książki telefonicznej . kv -> $nazwa , $liczba { powiedz "Liczba dla $nazwa: $liczba" ; }
Raku nie ma żadnych referencji. Skróty mogą być przekazywane jako pojedyncze parametry, które nie są spłaszczane. Jeśli chcesz się upewnić, że podprogram akceptuje tylko skróty, użyj % w podpisie.
podrzędna -lista-telefoniczna ( %pb ) { dla %pb . kv -> $nazwa , $liczba { powiedz "Liczba dla $nazwa: $liczba" ; } } lista-książki-telefonicznej ( %książka-telefoniczna );
Zgodnie ze stopniowym typowaniem , skróty mogą podlegać ograniczeniom typu, ograniczając zestaw ważnych kluczy do określonego typu.
# Zdefiniuj hash, którego klucze mogą być tylko liczbami całkowitymi (typ "Int"). my %numbersWithNames { Int }; # Klucze muszą być liczbami całkowitymi, tak jak w tym przypadku. %numbersWithNazwy . pchnij ( 1 => "jeden" ); # Spowoduje to błąd, ponieważ łańcuchy jako klucze są nieprawidłowe. %numbersWithNazwy . push ( "klucz" => "dwa" );
PHP
Typ wbudowanej tablicy PHP jest w rzeczywistości tablicą asocjacyjną. Nawet przy użyciu indeksów numerycznych, PHP wewnętrznie przechowuje tablice jako tablice asocjacyjne. Tak więc PHP może mieć tablice indeksowane numerycznie w sposób niesekwencyjny. Klucze muszą być typu całkowitego (liczby zmiennoprzecinkowe są obcinane do liczby całkowitej) lub typu łańcuchowego, podczas gdy wartości mogą być dowolnego typu, w tym innych tablic i obiektów. Tablice są heterogeniczne: pojedyncza tablica może mieć klucze różnych typów. Tablice asocjacyjne PHP mogą być używane do reprezentowania drzew, list, stosów, kolejek i innych typowych struktur danych, które nie są wbudowane w PHP.
Tablicę asocjacyjną można zadeklarować przy użyciu następującej składni:
$książka telefoniczna = tablica (); $telefon [ 'Sally Smart' ] = '555-9999' ; $telefoniczna [ 'John Doe' ] = '555-1212' ; $książka telefoniczna [ 'J. Losowy haker' ] = '555-1337' ; // lub $phonebook = array ( 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '555-1337' , ); // lub od PHP 5.4 $phonebook = [ 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Losowy haker' => '555-1337' , ]; // lub $phonebook [ 'contacts' ][ 'Sally Smart' ][ 'number' ] = '555-9999' ; $phonebook [ 'contacts' ][ 'John Doe' ][ 'numer' ] = '555-1212' ; $phonebook [ 'kontakty' ][ 'J. Losowy haker' ][ 'liczba' ] = '555-1337' ;
PHP może przechodzić przez tablicę asocjacyjną w następujący sposób:
foreach ( $książka telefoniczna jako $nazwa => $liczba ) { echo 'Numer dla' , $nazwa , ':' , $liczba , " \n " ; } // W ostatnim przykładzie tablica jest używana w ten sposób foreach ( $phonebook [ 'contacts' ] as $name => $num ) { echo 'Nazwa: ' , $name , ', number: ' , $num [ ' liczba' ], " \n " ; }
PHP posiada rozbudowany zestaw funkcji do operowania na tablicach.
Tablice asocjacyjne, które mogą używać obiektów jako kluczy zamiast łańcuchów i liczb całkowitych, można zaimplementować za pomocą klasy SplObjectStorage
ze standardowej biblioteki PHP (SPL).
Szczupak
Pike ma wbudowaną obsługę tablic asocjacyjnych, które są określane jako mapowania. Odwzorowania są tworzone w następujący sposób:
mapping ( string : string ) phonebook = ([ "Sally Smart" : "555-9999" , "John Doe" : "555-1212" , "J. Random Hacker" : "555-1337" ]);
Dostęp i testowanie obecności w odwzorowaniach odbywa się za pomocą operatora indeksowania. Więc phonebook["Sally Smart"]
zwróci ciąg "555-9999"
, a phonebook["John Smith"]
zwróci 0.
Iterację przez mapowanie można wykonać za pomocą foreach
:
foreach ( książka telefoniczna ; ciąg klucz ; wartość ciągu ) { write ( "%s:%s \n " , klucz , wartość ); }
Lub używając obiektu iteratora:
mapowanie . Iterator i = get_iterator ( książka telefoniczna ); while ( i -> index ()) { write ( "%s:%s \n " , i -> index (), i -> wartość ()); ja -> następny (); }
Elementy odwzorowania można usunąć za pomocą funkcji m_delete
, która zwraca wartość usuniętego indeksu:
string sallys_number = m_delete ( książka telefoniczna , "Sally Smart" );
Postscriptum
W języku PostScript tablice asocjacyjne nazywane są słownikami. W PostScript poziomu 1 muszą być tworzone jawnie, ale poziom 2 wprowadził bezpośrednią deklarację przy użyciu składni podwójnych nawiasów:
% Deklaracja poziomu 1 3 dict dup początek /red (rouge) def /green (vert) def /blue (bleu) def end % Deklaracja poziomu 2 << /red (rot) /green (gruen) /blue (blau) >> % Obie metody pozostawiają słownik na stosie operandów
Dostęp do słowników można uzyskać bezpośrednio, używając get
lub niejawnie, umieszczając słownik na stosie słowników, używając begin
:
% Z poprzednimi dwoma słownikami wciąż na stosie argumentów /red get print % wyjścia 'rot' start zielony print % wyjścia 'vert' koniec
Zawartość słownika można iterować za pomocą forall
, ale nie w określonej kolejności:
% Przykład poziomu 2 << /Ten 1 /Tamten 2 /Inny 3 >> { exch =print ( is ) print == } forall
Które mogą wyprowadzać:
To jest 2 To jest 1 Inne to 3
Słowniki można powiększać (do określonego rozmiaru tylko na poziomie 1) lub zmieniać za pomocą put
, a wpisy można usuwać za pomocą undef
:
% zdefiniuj słownik do łatwego ponownego użycia: /MyDict << /rouge (czerwony) /vert (gruen) >> def % dodaj do niego MyDict /bleu (niebieski) put % zmień go MyDict /vert (zielony) put % usuń coś MyDict /różowy undef
Prolog
Niektóre wersje Prologu zawierają narzędzia słownikowe („dict”).
Pyton
W Pythonie tablice asocjacyjne nazywane są „ słownikami ”. Literały słownikowe są oddzielone nawiasami klamrowymi:
książka telefoniczna = { „Sally Smart” : „555-9999” , „John Doe” : „555-1212” , „J. Random Hacker” : „553-1337” , }
Dostęp do elementów słownika można uzyskać za pomocą operatora indeksowania tablicy:
>>> książka telefoniczna [ "Sally Smart" ] '555-9999'
Zapętlaj iterację przez wszystkie klucze słownika:
>>> dla wpisu w książce telefonicznej : ... drukuj ( klawisz , książka telefoniczna [ klawisz ]) Sally Smart 555 - 9999 J . Losowy haker 553 - 1337 John Doe 555 - 1212
Iteracja po krotkach (klucz, wartość):
>>> dla klucza , wartość w książce telefonicznej . pozycje (): ... drukuj ( klucz , wartość ) Sally Smart 555 - 9999 J . Przypadkowy haker 553 - 1337 John Doe 555 - 1212
Klucze słownika można indywidualnie usuwać za pomocą instrukcji del
. Odpowiednią wartość można zwrócić przed usunięciem pary klucz-wartość za pomocą metody „pop” typu „dict”:
>>> del phonebook [ "John Doe" ] >>> val = phonebook . pop ( "Sally Smart" ) >>> książka telefoniczna . klucze () # Został tylko jeden klucz [ 'J. Przypadkowy haker ]
Python 2.7 i 3.x obsługują również rozumienie listy słowników , zwartą składnię do generowania słownika z dowolnego iteratora:
0 0
>>> dyktat_kwadrat = { i : i * i dla i w zakresie ( 5 )} >>> dykt_kwadrat { : , 1 : 1 , 2 : 4 , 3 : 9 , 4 : 16 } >>> { klucz : wartość dla klucz , wartość w książce telefonicznej . pozycje () jeśli „J” w kluczu } { „J. Losowy haker” : „553-1337” , „John Doe” : „555-1212” }
Ściśle mówiąc, słownik jest nadzbiorem tablicy asocjacyjnej, ponieważ ani klucze, ani wartości nie są ograniczone do jednego typu danych. Można by pomyśleć o słowniku jako o „liście asocjacyjnej”, używając nomenklatury Pythona. Na przykład, następujące jest również uzasadnione:
książka telefoniczna = { „Sally Smart” : „ 555-9999” , „John Doe” : brak , „J. Random Hacker” : -3,32 , 14 : „555-3322” , }
Klucze słownika muszą mieć niezmienny typ danych. W Pythonie ciągi znaków są niezmienne ze względu na sposób ich implementacji.
Czerwony
W kolorze czerwonym wbudowana mapa!
datatype zapewnia tablicę asocjacyjną, która odwzorowuje wartości typu word, string i klucza skalarnego na wartości dowolnego typu. Tabela skrótów jest używana wewnętrznie do wyszukiwania.
Mapę można zapisać jako literał, na przykład #(klucz1 wartość1 klucz2 wartość2 ...)
lub można ją utworzyć za pomocą make map! [klucz1 wartość1 klucz2 wartość2 ...]
:
Czerwony [ Tytuł: "Moja mapa" ] moja-mapa: stwórz mapę! [ "Sally Smart" "555-9999" "John Doe" "555-1212" "J. Random Hacker" "553-1337" ] ; Kolor czerwony zachowuje wielkość liter zarówno dla kluczy, jak i wartości, jednak w wyszukiwaniu domyślnie nie jest rozróżniana wielkość liter; możliwe jest wymuszenie uwzględniania wielkości liter przy użyciu uściślenia <code>/case</code> dla <code>select</code> i <code>put</code>. ; Oczywiście możliwe jest użycie wartości <code>word!</code> jako kluczy, w takim przypadku ogólnie preferowane jest użycie wartości <code>set-word!</code> podczas tworzenia mapy, ale dowolnego typu słowa może służyć do wyszukiwania lub tworzenia. moja-inna-mapa: stwórz mapę! [ foo: 42 bar: fałsz ] ; Zauważ, że blok nie jest w żaden sposób zmniejszany ani oceniany, dlatego w powyższym przykładzie klawisz <code>bar</code> jest powiązany raczej z <code>word!</code> <code>false</code> niż wartość <code>logic!</code> false; można użyć dosłownej składni, jeśli jest to pożądane: my-other-map: make map! [ foo: 42 bar: # [ fałsz ]] ; lub klucze można dodać po utworzeniu: my-other-map: make map! [ foo: 42 ] moja-inna-mapa /bar: false ; Wyszukiwanie można zapisać za pomocą notacji <code>path!</code> lub akcji <code>select</code>: select my-map "Sally Smart" my-other-map /foo ; Możesz także przeglądać wszystkie klucze i wartości za pomocą <code>foreach</code>: foreach [ wartość klucza ] my-map [ print [ klucz „jest powiązany z” wartością ] ] ; Klucz można usunąć za pomocą <code>remove/key</code>: remove /key my-map "Sally Smart"
REXX
W języku REXX tablice asocjacyjne nazywane są „zmiennymi macierzystymi” lub „zmiennymi złożonymi”.
KLUCZ = KSIĄŻKA TELEFONICZNA „Sally Smart” . KLUCZ = „555-9999” KLUCZ = „John Doe” KSIĄŻKA TELEFONICZNA . KLUCZ = „555-1212” KLUCZ = „J. KSIĄŻKA TELEFONICZNA przypadkowego hakera . KLUCZ = „553-1337”
Zmienne macierzyste z klawiszami numerycznymi zwykle zaczynają się od 1 i idą w górę. Zmienna rdzenia z kluczem 0 zgodnie z konwencją zawiera całkowitą liczbę elementów w temacie:
0 NAZWA . 1 = NAZWA „Sally Smart” . 2 = NAZWA „John Doe” . 3 = „J. NAZWA losowego hakera . = 3
REXX nie ma łatwego sposobu na automatyczny dostęp do kluczy zmiennej macierzystej; i zazwyczaj klucze są przechowywane w oddzielnej tablicy asocjacyjnej z klawiszami numerycznymi.
Rubin
W języku Ruby tablica skrótów jest używana w następujący sposób:
książka telefoniczna = { 'Sally Smart' => '555-9999' , 'John Doe' => '555-1212' , 'J. Random Hacker' => '553-1337' } książka telefoniczna [ 'John Doe' ]
Ruby obsługuje zapętlanie hash i iterację z następującą składnią:
irb(main):007:0> ### iteracja po kluczach i wartościach irb(main):008:0* książka telefoniczna . każdy { | klucz , wartość | stawia klucz + " => " + wartość } Sally Smart => 555-9999 John Doe => 555-1212 J. Random Hacker => 553-1337 => {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337"} irb(main):009:0> ### iteruj tylko klawisze irb(main):010:0* książka telefoniczna . każdy_klucz { | klucz | umieszcza klucz } Sally Smart John Doe J. Random Hacker => {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337 "} irb(main):011:0> ### iteruj tylko wartości irb(main):012:0* książka telefoniczna . każda_wartość { | wartość | stawia wartość } 555-9999 555-1212 553-1337 => {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553- 1337"}
Ruby obsługuje również wiele innych przydatnych operacji na skrótach, takich jak łączenie skrótów, wybieranie lub odrzucanie elementów spełniających określone kryteria, odwracanie (zamiana kluczy i wartości) oraz spłaszczanie skrótu w tablicę.
Rdza
Standardowa biblioteka Rust zawiera mapę mieszającą ( std::collections::HashMap
) i mapę B-drzewa ( std::collections::BTreeMap
). Dzielą kilka metod o tych samych nazwach, ale mają różne wymagania dotyczące typów kluczy, które można wstawić. HashMap wymaga kluczy do implementacji cech Eq
( relacja równoważności ) i Hash
(haszowalność) i przechowuje wpisy w nieokreślonej kolejności, a BTreeMap wymaga
cechy
Ord (
total order ) dla swoich kluczy i przechowuje wpisy w kolejności określonej przez typ klucza. Kolejność jest odzwierciedlana przez domyślne iteratory.
użyj std :: kolekcje :: HashMap ; niech mut phone_book = HashMap :: new (); książka_telefoniczna . wstaw ( "Sally Smart" , "555-9999" ); książka_telefoniczna . wstaw ( "John Doe" , "555-1212" ); książka_telefoniczna . wstaw ( "J. Random Hacker" , "555-1337" );
Domyślne iteratory odwiedzają wszystkie wpisy jako krotki. Iteratory HashMap
odwiedzają wpisy w nieokreślonej kolejności, a iterator BTreeMap
odwiedza wpisy w kolejności określonej przez typ klucza.
for ( nazwa , numer ) w & phone_book { println! ( "{} {}" , imię , liczba ); }
Istnieje również iterator dla kluczy:
dla nazwiska w phone_book . klucze () { println! ( "{}" , imię ); }
Gwara
S-Lang ma typ tablicy asocjacyjnej:
książka telefoniczna = Assoc_Type []; książka telefoniczna ["Sally Smart"] = "555-9999" książka telefoniczna ["John Doe"] = "555-1212" książka telefoniczna ["J. Random Hacker"] = "555-1337"
Możesz także przechodzić przez powiązaną tablicę na kilka sposobów:
foreach nazwa (książka telefoniczna) { vmessage ("%s %s", nazwa, książka telefoniczna[nazwa]); }
Aby wydrukować posortowaną listę, lepiej jest skorzystać z silnego wsparcia S-lang dla standardowych tablic:
klucze = assoc_get_keys(książka telefoniczna); i = array_sort(klucze); vals = assoc_get_values(książka telefoniczna); array_map (Void_Type, &vmessage, "%s %s", klucze[i], wartości[i]);
Scala
Scala zapewnia niezmienną klasę Map
jako część struktury scala.collection
:
val phonebook = Mapa ( "Sally Smart" -> "555-9999" , "John Doe" -> "555-1212" , "J. Random Hacker" -> "553-1337" )
Wnioskowanie o typie Scali zdecyduje, że jest to Map[String, String]
. Aby uzyskać dostęp do tablicy:
książka telefoniczna . dostać ( "Sally Smart" )
To zwraca typ Option
, odpowiednik Scali monady Maybe w Haskell.
Pogawędka
W Smalltalk używany jest słownik
:
książka telefoniczna := Słownik nowy . książkę telefoniczną pod adresem: „Sally Smart” wpisz: „555-9999” . książka telefoniczna pod adresem: „John Doe” wpisz: „555-1212” . książka telefoniczna pod adresem: „J. Random Hacker” wpisał: „553-1337” .
Aby uzyskać dostęp do wpisu, wiadomość #at:
jest wysyłana do obiektu słownika:
książka telefoniczna pod adresem: „Sally Smart”
Co daje:
'555-9999'
Słownik haszuje lub porównuje w oparciu o równość i oznacza zarówno klucz, jak i wartość jako silne odniesienia . Istnieją warianty, w których hash/porównaj tożsamość (IdentityDictionary) lub zachowaj słabe referencje (WeakKeyDictionary / WeakValueDictionary). Ponieważ każdy obiekt implementuje #hash, dowolny obiekt może być użyty jako klucz (i oczywiście również jako wartość).
SNOBOL
SNOBOL jest jednym z pierwszych (jeśli nie pierwszym) języków programowania wykorzystujących tablice asocjacyjne. Tablice asocjacyjne w SNOBOL-u nazywane są tabelami.
KSIĄŻKA TELEFONICZNA = TABELA () KSIĄŻKA TELEFONICZNA [ 'Sally Smart' ] = '555-9999' KSIĄŻKA TELEFONICZNA [ 'John Doe' ] = '555-1212' KSIĄŻKA TELEFONICZNA [ 'J. Losowy haker' ] = '553-1337'
standardowy ML
Standard SML'97 języka programowania Standard ML nie udostępnia żadnych kontenerów asocjacyjnych. Jednak różne implementacje Standard ML zapewniają kontenery asocjacyjne.
Biblioteka popularnej implementacji Standard ML of New Jersey (SML/NJ) zapewnia sygnaturę (trochę jak „interfejs”), ORD_MAP
, która definiuje wspólny interfejs dla uporządkowanych funkcjonalnych (niezmiennych) tablic asocjacyjnych. Istnieje kilka ogólnych funktorów — BinaryMapFn
, ListMapFn
, RedBlackMapFn
i SplayMapFn
— które umożliwiają tworzenie odpowiedniego typu uporządkowanej mapy (typy to samobalansujące się drzewo wyszukiwania binarnego , posortowana lista asocjacji , drzewo czerwono-czarne i drzewo splay , odpowiednio) przy użyciu struktury dostarczonej przez użytkownika do opisania typu klucza i komparatora. Funktor zwraca strukturę zgodną z ORD_MAP
. Ponadto istnieją dwa predefiniowane moduły dla tablic asocjacyjnych wykorzystujących klucze całkowite: IntBinaryMap
i IntListMap
.
-Struktura StringMap = BinaryMapFn ( typ struktury ord_key = string val porównania = String . porównania koniec ) ; struktura StringMap : ORD_MAP - val m = StringMap . wstaw ( StringMap . pusty , „Sally Smart” , „555-9999” ) val m = StringMap . wstaw ( m , „John Doe” , „555-1212” ) val m = StringMap . wstaw ( m , "J. Random Hacker" , "553-1337" ); val m = T { cnt = 3 , key = "John Doe" , left = T { cnt = 1 , key = "J. Random Hacker" , left = E , right = E , value = "553-1337" }, right = T { cnt = 1 , key = "Sally Smart" , left = E , right = E , value = "555-9999" }, value = "555-1212" } : ciąg StringMap . mapa — StringMap . znajdź ( m , "John Doe" ); val it = NIEKTÓRE "555-1212" : opcja łańcucha
SML/NJ zapewnia również polimorficzną tablicę mieszającą:
0
- wyjątek Nie znaleziono ; wyjątek NotFound - val m : ( string , string ) HashTable . hash_table = HashTable . mkTable ( HashString . hashString , op =) ( 3 , nie znaleziono ); val m = HT { eq_pred = fn , hash_fn = fn , n_items = ref , not_found = Not Found ( - ), table = ref [ |NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , NIL , ZERO ,... | ]} : ( string , string ) HashTable . hash_table - HashTable . wstaw m ( "Sally Smart" , "555-9999" ); val it = () : unit - HashTable . wstaw m ( "John Doe" , "555-1212" ); val it = () : unit - HashTable . wstaw m ( "J. Random Hacker" , "553-1337" ); val it = () : jednostka HashTable . znajdź m "John Doe" ; (* zwraca BRAK, jeśli nie znaleziono *) val it = SOME "555-1212" : opcja ciągu znaków - HashTable . wyszukaj m "John Doe" ; (* zgłasza wyjątek, jeśli nie został znaleziony *) val it = "555-1212" : string
Obsługiwane są również monomorficzne tablice skrótów przy użyciu funktora HashTableFn
.
Inna standardowa implementacja ML, Moscow ML , również zapewnia pewne kontenery asocjacyjne. Po pierwsze, zapewnia polimorficzne tablice skrótów w Polyhash
. Ponadto niektóre mapy funkcjonalne z powyższej biblioteki SML/NJ są dostępne jako Binarymap
, Splaymap
i Intmap
.
Tcl
Istnieją dwa udogodnienia Tcl , które obsługują semantykę tablic asocjacyjnych. „Tablica” to zbiór zmiennych. „Dykt” to pełna implementacja tablic asocjacyjnych.
szyk
ustaw { książka telefoniczna ( Sally Smart )} 555 - 9999 ustaw jan { John Doe } ustaw książkę telefoniczną ( $jan ) 555 - 1212 ustaw { książka telefoniczna ( J. Random Hacker )} 553 - 1337
Jeśli w nazwie zmiennej występuje znak spacji, nazwa musi być pogrupowana za pomocą nawiasów klamrowych (podstawianie nie jest wykonywane) lub cudzysłowów (podstawianie jest wykonywane).
Alternatywnie, kilka elementów tablicy można ustawić za pomocą jednego polecenia, prezentując ich odwzorowania jako listę (słowa zawierające białe znaki są w nawiasach klamrowych):
zestaw tablic książka telefoniczna [ lista { Sally Smart } 555 - 9999 { John Doe } 555 - 1212 { J. Random Hacker } 553 - 1337 ]
Aby uzyskać dostęp do jednego wpisu tablicy i umieścić go na standardowym wyjściu:
umieszcza $telefon ( Sally \ Smart )
Który zwraca ten wynik:
555-9999
Aby pobrać całą tablicę jako słownik:
tablica pobierz książkę telefoniczną
Rezultatem może być (kolejność kluczy jest nieokreślona, nie dlatego, że słownik jest nieuporządkowany, ale dlatego, że tablica to):
{ Sally Smart } 555-9999 { J. Random Hacker } 553 - 1337 { John Doe } 555 - 1212
dyktować
ustaw książkę telefoniczną [ dict create { Sally Smart } 555 - 9999 { John Doe } 555 - 1212 { J. Random Hacker } 553 - 1337 ]
Aby wyszukać element:
dyktuj pobierz $książkę telefoniczną { John Doe }
Aby iterować przez dyktando:
foreach { nazwa numer } $telefon { stawia "nazwa: $nazwa\nnumer: $liczba" }
Visual Basic
Visual Basic może używać klasy Dictionary z Microsoft Scripting Runtime (która jest dostarczana z Visual Basic 6). Nie ma standardowej implementacji wspólnej dla wszystkich wersji:
' Wymaga odniesienia do SCRRUN.DLL we właściwościach projektu Wyczyść książkę telefoniczną jako nowy słownik książka telefoniczna . Dodaj książkę telefoniczną „Sally Smart” , „555-9999” . Item ( "John Doe" ) = "555-1212" phoneBook ( "J. Random Hacker" ) = "553-1337" Dla każdego nazwiska w phoneBook MsgBox nazwa & " = " & phoneBook ( nazwa ) Dalej
Visual Basic .NET
Visual Basic .NET używa klas kolekcji dostarczonych przez .NET Framework .
kreacja
Poniższy kod ilustruje tworzenie i wypełnianie słownika (zobacz przykład języka C# na tej stronie, aby uzyskać dodatkowe informacje):
Dim dic jako nowy system . Kolekcje . ogólny . Słownik ( łańcuchowy , łańcuchowy ) dic . _ Dodaj ( "Sally Smart" , "555-9999" ) dic ( "John Doe" ) = "555-1212" dic . Pozycja ( "J. Random Hacker" ) = "553-1337"
Alternatywną składnią byłoby użycie inicjatora kolekcji , który kompiluje się do poszczególnych wywołań Add
:
Dim dic jako nowy system . Kolekcje . Słownik ( łańcuchowy , łańcuchowy ) z { { "Sally Smart" , "555-9999" }, { "John Doe" , "555-1212" }, { "J. Random Hacker" , "553-1337" } } }
Dostęp na klucz
Przykład demonstrujący dostęp (zobacz dostęp w języku C# ):
Dim sallyNumber = dic ( "Sally Smart" ) ' lub Dim sallyNumber = dic . Przedmiot ( "Sally Smart" )
Dim wynik As String = Nic Dim sallyNumber = If ( dic . TryGetValue ( "Sally Smart" , wynik ), wynik , "n/a" )
Wyliczenie
Przykład demonstrujący wyliczanie (zobacz wyliczanie #C# ):
' przejdź przez kolekcję i wyświetl każdy wpis. Dla każdego kvp As KeyValuePair ( z ciągu , ciąg ) w konsoli dic . WriteLine ( "Numer telefonu dla {0} to {1}" , kvp . Klucz , kvp . Wartość ) Dalej
Windows PowerShell
W przeciwieństwie do wielu innych interpreterów wiersza poleceń , Windows PowerShell ma wbudowaną obsługę definiowania tablic asocjacyjnych na poziomie języka:
$telefon = @{ 'Sally Smart' = '555-9999' ; 'John Doe' = '555-1212' ; 'J. Losowy haker' = '553-1337' }
Podobnie jak w JavaScript, jeśli nazwa właściwości jest prawidłowym identyfikatorem, cudzysłowy można pominąć:
$myOtherObject = @{ foo = 42 ; słupek = $fałsz }
Wpisy mogą być oddzielone średnikiem lub znakiem nowej linii:
$myOtherObject = @{ foo = 42 bar = $false ; zaz = 3 }
Klucze i wartości mogą być obiektami dowolnego typu .NET :
$now = [DateTime] :: Teraz $jutro = $teraz . AddDays ( 1 ) $ProcessDeletionSchedule = @{ ( Notatnik Get-Process ) = $teraz ( Get-Process calc ) = $jutro }
Możliwe jest również utworzenie pustej tablicy asocjacyjnej i późniejsze dodawanie do niej pojedynczych wpisów lub nawet innych tablic asocjacyjnych:
$telefon = @{} $telefon += @{ 'Sally Smart' = '555-9999' } $telefon += @{ 'John Doe' = '555-1212' ; 'J. Losowy haker' = '553-1337' }
Nowe wpisy można również dodawać za pomocą operatora indeksu tablicy, operatora właściwości lub metody Add()
bazowego obiektu .NET:
$telefoniczna = @{} $telefoniczna [ 'Sally Smart' ] = '555-9999' $telefoniczna . 'John Doe' = '555-1212' $książka telefoniczna . Dodaj ( 'J. Random Hacker' , '553-1337' )
Aby usunąć odwołania do przypisanych obiektów, można użyć operatora indeksu tablicy, operatora właściwości lub sparametryzowanej właściwości Item()
obiektu .NET:
$książka telefoniczna [ 'Sally Smart' ] $książka telefoniczna . $książka telefoniczna „John Doe” . Przedmiot ( „J. Random Hacker” )
Możesz przejść przez tablicę asocjacyjną w następujący sposób:
$książka telefoniczna . klucze | foreach { "Numer dla {0}: {1}" -f $_ , $książka telefoniczna . $_ }
Wpis można usunąć za pomocą metody Remove()
bazowego obiektu .NET:
$książka telefoniczna . Usuń ( „Sally Smart” )
Można dodać tablice skrótów:
$hash1 = @{ a = 1 ; b = 2 } $hash2 = @{ c = 3 ; d = 4 } $hash3 = $hash1 + $hash2
Obsługa formatów serializacji danych
Wiele formatów serializacji danych obsługuje również tablice asocjacyjne (patrz ta tabela )
JSON
W formacie JSON tablice asocjacyjne są również nazywane obiektami. Klucze mogą być tylko łańcuchami.
{ „Sally Smart” : „555-9999” , „John Doe” : „555-1212” , „J. Random Hacker” : „555-1337” }
YAML
Tablice asocjacyjne YAML są również nazywane elementami mapy lub parami klucz-wartość. YAML nie nakłada żadnych ograniczeń na typy kluczy; w szczególności nie są one ograniczone do wartości skalarnych lub łańcuchowych.
Sally Smart : 555-9999 John Doe : 555-1212 J. Random Hacker : 555-1337