Jak przejść przez хешу w Perl

Zadanie. W kodzie programu Perl jest hash %h. W tym хеше jakies pary wartości. Trzeba przejść przez wszystkie elementy mieszania i wykonać czynności z każdym elementem.

Spacer po хешу z pomocą foreach

Najczęściej, najbardziej wygodny sposób, aby obejść hash to wykorzystać foreach. Oto przykład kodu:

▶ Run
#!/usr/bin/perl

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

foreach my $key (keys %h) {
    print "$key - $h{$key}\n";
}

Wszystko jest bardzo proste. Najpierw tworzymy skrót %h , w którym znajdują się trzy pary wartości. Dalej znajduje się pętla. Z pomocą keys %h otrzymaliśmy listę wszystkich kluczy mieszania (w tym przykładzie wiersza 'a', 'b' i 'asdf'). Pasek z kluczykiem umieszczony w zmiennej $key i wykonywane jest ciało pętli, potem w $key umieszcza się następujący klucz mieszania i ponownie wykonywane jest ciało pętli, i tak się dzieje jest dla wszystkich kluczy.

Jeżeli zapisz ten kod w pliku script.pl i wykonać go perl script.pl, to na ekranie pojawi się zestaw par wartości, zawarte w хеше:

b - 20
asdf - Hello
a - 1

Hesh — to неупорядоченный zestaw par wartości. I na wniosku to dobrze widać — taki porządek, w którym zostały wycofane elementy mieszania nie są zgodne z porządkiem, w którym zostały zdefiniowane w kodzie programu. A jeśli uruchomić ten skrypt kilka razy, kolejność elementów na wyjściu będzie się zmieniać. keys %h zwraca listę kluczy mieszania w kolejności losowej. Jeśli chcesz aby porządek był zawsze ten sam, to w tym celu, na przykład, można użyć, sortowanie foreach my $key (sort keys %h) {.

Przejść przez хешу z pomocą while i each

Innym sposobem, aby obejść cały hash — to użyć cykl while i słowo kluczowe each. Oto kod, który działa tak samo jak w poprzednim przykładzie:

▶ Run
#!/usr/bin/perl

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

while (my ($key, $value) = each %h) {
    print "$key - $value\n";
}

each %h zwraca listę z dwóch elementów — klucz mieszania i odpowiadająca mu wartość. Dokładnie tak samo, jak i w przypadku keys kolejność w którym each zwraca pary wartości nie jest zdefiniowany. Różne starty jednej i tej samej programy będą zwracać pary w różnych formacjach.

Możemy przypisać wartości które zwrócił each w zmienne. each pamięta, jakie pary mieszania on już wydał i przy następnym użyciu zwróci innej pary wartości. Tak będzie trwać aż each nie zwróci wszystkie pary, wtedy on zwróci pustą listę. Aż each zwraca parę wartości wykonywane jest ciało while cyklu, jak tylko on zwraca pustą listę, cykl whilekończy się.

Zmiana wartości w хеше

Podczas korzystania z foreach cyklu, keys %h odbywa się tylko jeden raz. Podczas korzystania z whilecyklu each wykonywane podczas każdej iteracji.

Poszerzać poprzednie zadanie — musimy nie tylko wyświetlać wszystkie elementy mieszania, ale jeszcze i zastąpić je. To zupełnie bez problemu można to zrobić przy użyciu foreach i keys:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

foreach my $key (keys %h) {
    print "$key - $h{$key}\n";
    $h{ $key . $key } = $h{$key};
    delete $h{$key};
}

print Dumper \%h;

Wyjście z programu:

asdf - Hello
a - 1
b - 20
$VAR1 = {
          'bb' => 20,
          'aa' => 1,
          'asdfasdf' => 'Hello'
        };

Ale tak się nie da zrobić przy korzystać each:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

while (my ($key, $value) = each %h) {
    print "$key - $value\n";

    # error!
    $h{ $key . $key } = $value;
    delete $h{$key};
}

print Dumper \%h;

Po uruchomieniu programu na ekranie pojawi się coś takiego:

Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
b - 20
bb - 20
bbbb - 20
asdf - Hello
$VAR1 = {
          'asdfasdf' => 'Hello',
          'bbbbbbbb' => 20,
          'a' => 1
        };

each zwróciło kilka wartości z mieszania, a potem zmieniamy hesh. Dzieje się następna iteracja pętli i eachzwraca kilka zmodyfikowanego mieszania i może zwrócić tę parę, która właśnie dołączyła.

Więc jeśli podczas przeszukiwania mieszania trzeba go zmienić, to trzeba użyć foreach i keys. Podczas korzystania z while i each program będzie działał poprawnie.

Tematy pokrewne

Inne artykuły