Hash * este similar cu matricea pe care am discutat mai sus, prin faptul că este un set de date scalare ale căror elemente individuale sunt selectate de valoarea indexului. Spre deosebire de o matrice, valorile indexului unui hash nu sunt numere întregi mici, ne-negative, ci scalare arbitrare. Aceste scalare (chei numite) sunt folosite pentru a prelua valorile dintr-o matrice.
Elementele unui hash nu stau într-o anumită ordine. Puteți să le tratați ca un teanc de cărți bibliografice. Partea superioară a fiecărui card este cheia, iar jumătatea inferioară este valoarea. De fiecare dată când puneți o valoare în hash, se creează o nouă carte. Când trebuie să modificați o valoare, specificați o cheie și Perl găsește cardul necesar. Prin urmare, ordinea cardurilor, de fapt, nu joacă un rol. Perl stochează toate cardurile (adică perechi cheie-valoare) într-o comandă internă specială, ceea ce face mai ușor să căutați o anumită carte, astfel că atunci când căutați, nu trebuie să vă uitați prin toate perechile. Ordinea de stocare a cardurilor nu poate fi schimbată, deci nu încercați nici măcar **.
Numele variabilei hash constă într-un semn procentual (%) și o literă urmată de alte litere, numere și subliniere de la zero sau mai mult. Cu alte cuvinte, partea din nume după semnul procentului este similară cu
* În documentele vechi, numite tablouri asociative hashes, dar am fost atât de obosit să se aplice o astfel de extindere a conceptului de un astfel de termen polisilabic, ne-am decis să-l înlocuiască cu un mult mai mult succes în monosilabic.
** Module cum ar fi IxHash și DB_fiIe oferă un anumit grad de comandă, dar cu prețul unei degradări semnificative a performanței.
partea corespunzătoare a numelor variabilelor scalare și a matricelor. Mai mult decât atât, la fel cum nu există nici o legătură între $ și @fred Fred, hash% variabila fred nu are nimic de-a face cu aceste obiecte.
Cel mai adesea, un hash este creat și folosit referindu-se la elementele sale, nu la întreg hash. Fiecare element hash este o variabilă scalară separată, accesibilă printr-un index, care este o valoare de șir și se numește o cheie. Deci, apelul la elementele hash% fred se face prin specificarea $ fred<$ключ> , unde cheia $ este orice expresie scalară. Din nou, subliniem că apelul la elementul hash necesită o sintaxă diferită, mai degrabă decât trimiterea la întregul hash întreg.
Ca și în cazul matricelor, elementele hash sunt create prin atribuirea de valori:
$ fred == "bbb"; # Creează un "aaa" cheie, valoarea "bbb" $ fred (234.5> = 456,7; # creează tasta "5 234", valoarea 456.7
Utilizând acești operatori, două elemente sunt create în hash. La accesarea ulterioară a elementelor (prin tastele specificate) valorile înregistrate anterior sunt returnate:
print $ fred ("aaa"); # afișează "bbb" $ fred
Atunci când se referă la valoarea unui element inexistent returnează UNDEF (ca la accesarea elementului de matrice variabilă scalară absent sau nedefinit).
Reprezentarea laterală a unui hash
Este posibil să fie necesar să se adreseze întregului hash - de exemplu, pentru a inițializa sau copiați-l la un alt hash. De fapt, Perl nu are nici un format literal pentru hash, așa că apare pur și simplu ca o listă. Fiecare pereche de elemente din această listă (în care trebuie să existe întotdeauna un număr par de elemente) specifică cheia și valoarea corespunzătoare. Această vizualizare extinsă poate fi atribuită unui alt hash, care apoi recreează același hash. Cu alte cuvinte:
@ fred_list =% fred; # @ fred_list primește valoarea
# ( "Aaa", "bbb", "234.5", "456,7")% barney = @fred_list; # crea% barney ca% fred% barney =% fred; # Metoda accelerată de realizarea acestei sarcini% buna "(" aaa "" bbb "" 234.5 "" 456,7 „);
# creați neted ca% fred din valori literale
Ordinea perechilor cheie-valoare în acest format extins este arbitrară și nu poate fi controlată. Chiar dacă schimbați orice valori sau de a crea în întregime hash listă extinsă returnat va fi în continuare în ordinea în care Perl a ales pentru a asigura accesul eficient la elementele individuale. Este imposibil să contezi pe orice secvență specifică.
% rub = original; # copie de la% original la% rub
Utilizând operația inversă, puteți crea un hash în care cheile și valorile sunt schimbate:
% înapoi = inversă% normal;
Desigur, în cazul în care% normală are două valori identice, în% în spate se vor transforma într-un singur element, astfel încât această operațiune se realizează cel mai bine doar peste hash-uri cu chei și valori unice.
Această secțiune afișează câteva funcții care sunt concepute pentru a gestiona hashes-urile.
Tastele funcționale (% imya_hesha) oferă o listă a tuturor cheie curente existente în hash% imya_hesha. Cu alte cuvinte, utilizarea acestei funcții este echivalentă cu revenirea lista tuturor elementelor numerotate cu numere impare (prima, a treia, a cincea, etc.) prin implementarea hash context% imya_hesha într-o listă, și le revine să funcționeze cheile în această ordine. Dacă nu există elemente în hash, funcția tastelor returnează o listă goală.
Să aplicăm această funcție la hash din exemplele anterioare:
Olist = chei (% fred); # @ lista primește valoarea ("aaa", 234.5) # sau (234.5, "aaa")
Ca toate celelalte funcții încorporate, parantezele nu sunt necesare: funcțiile% fred sunt identice cu tastele (% fred).
foreach $ cheie (chei (% fred)) (# o dată pentru fiecare valoare hash% fred
print "la cheia $ avem $ fred ($ key> \ n"; # show key and value>)
Acest exemplu arată, de asemenea, că elementele hash individuale pot fi interpolate în șiruri în ghilimele duble. Totuși, hash nu poate fi interpolat în acest fel *.
În contextul scalar, funcția tastelor furnizează numărul de elemente (perechi cheie-valoare) conținute în hash. De exemplu, puteți afla dacă hash-ul este gol, după cum urmează:
dacă (chei (% xeni)) <# если keys() не равно 0:
; # matricea nu este goală)
în timp ce (cheile (% xem) <10)
; # continuați ciclul până când există mai puțin de 10 elemente>
Pentru a afla dacă hash-ul este gol sau nu, trebuie doar să utilizați funcția% hash în contextul scalar:
dacă (% hash) (# dacă "adevărat", există ceva în ea
Valorile funcționale (% array_name) returnează o listă a tuturor valorilor curente ale șirului specificat în aceeași ordine în care tastele funcționale (% array_name> chei returnează Ca întotdeauna, între paranteze sunt opționale exemplu ..:
% nume = 0; # face% nume de familie gol nume final ("fred"> = "flintstone";
Numerele Olast = valori (tiastname); obțineți valori
Gama @lastnames va conține fie valori ("flintstone", "rubble"), fie ("moloz", "flintstone").
Pentru looping pe întreaga hash (de exemplu, pentru a testa fiecare element), puteți utiliza tastele funcționale, și obține valori prin întoarcere taste. Într-adevăr, această metodă este utilizată pe scară largă, dar există un mod mai eficient - să funcționeze fiecare (% imya_hesha), care returnează o pereche cheie-valoare ca o listă cu două elemente. Fiecare calcul al acestei funcții returnează următoarea pereche cheie-valoare pentru un hash, până când toate elementele sunt verificate. Dacă perechea nu mai este prezentă, fiecare returnează o listă goală.
* Este posibil, în principiu, cu ajutorul unei tăieturi, dar aici nu vorbim despre felii.
De exemplu, pentru a trece prin hash-ul ultimului nume din exemplul anterior, trebuie să utilizați ceva similar:
în timp ce (($ primul, $ last) = fiecare (% nume de familie))
print "Ultimul nume al primului $ este $ last \ n";
Atribuirea unei noi valori pentru hash-ul întreg face ca fiecare funcție să meargă la început. Adăugarea elementelor la hash și eliminarea elementelor din ea în timpul executării bucla ar putea "confunda" funcția fiecăruia (și probabil și dvs.).
% fred = ("aaa", "bbb", 234,5,34,56); # adăugați în două elemente fred ștergeți $ fred ("aaa">; # acum în hash% fred doar o pereche cheie-valoare
Ca și în cazul unei variabile array (în directorul sau literală), puteți utiliza o felie hash, care va face posibilă să se ocupe de nici unul dintre elementul său, și în același timp la un set de elemente. Luați, de exemplu, rezultatele jocului în skittles:
Toate acestea pot fi scrise într-o singură linie:
Dar chiar este prea lung, deci hai sa folosim felia de hash:
Asta e mult mai scurt. Puteți combina utilizarea unei șabloane de tip hash și interpolarea variabilă:
@players = dinam barney);
tipărire "sunt: @score (@players> \ n";
Modelele de șarpe pot fi, de asemenea, folosite pentru a îmbina un hash mic cu un hash mai mare. În acest exemplu, un hash mai mic are prioritate în sensul că dacă există chei duplicate, se folosește valoarea de la hash-ul mai mic:
Aici, scorul% de valoare hash se îmbină cu hash-ul liga%. Aceasta este echivalentă cu efectuarea unei operații mult mai lente:
% league = (% liga,% scor); = # combinați scorul% cu% ligă
1. Scrieți un program care citește un șir și apoi tipărește această linie și valoarea corespunzătoare conform tabelului de mai jos:
2. Scrieți un program care citește o serie de cuvinte (unul pe fiecare rând) la sfârșitul fișierului și apoi afișează un rezumat al numărului de câte ori sa întâlnit fiecare cuvânt. (Sarcină suplimentară: sortați cuvintele care apar pe ecran cu valorile lor ASCII în ordine ascendentă.)