In Perl sind Hashes (assoziative Arrays) ein mächtiges Werkzeug zur Speicherung von Schlüssel-Wert-Paaren. Allerdings erfordert die Arbeit mit ihnen Aufmerksamkeit, insbesondere beim gleichzeitigen Durchlaufen und Ändern der Struktur. Übersehene Details führen hier zu Fehlern, die schwer zu diagnostizieren sind.
Assoziative Arrays wurden bereits in frühen Versionen von Perl (Perl 1/2) eingeführt, was sie zu einer der ersten Sprachen mit vollständiger Unterstützung von Hashes auf Kernniveau machte. Im Laufe der Zeit entstanden zusätzliche Möglichkeiten: Iteration mit each, Entfernen (delete), massenhafte Transformation (map, grep) und der Umgang mit Struktur-/Inhaltsänderungen während der Durchquerung.
Das Durchlaufen eines Hashs und gleichzeitige Änderungen seines Inhalts, insbesondere das Entfernen von Elementen, kann zu unerwarteten Effekten führen: zum Überspringen von Elementen, zur mehrfachen Durchquerung derselben Schlüssel oder sogar zu endlosen Schleifen. Darüber hinaus ist die Reihenfolge der Schlüssel nicht garantiert und kann zwischen verschiedenen Perl-Versionen variieren.
each verwenden, da der interne Zeiger durcheinander gerät.keys sammeln, dann in einer separaten Schleife durch diese Liste gehen und entfernen.while (my ($k, $v) = each %h), um normal zu iterieren, aber kombinieren Sie es nicht mit delete innerhalb der Schleife, wenn Sie unerwartete Ergebnisse vermeiden möchten.Beispiel für korrektes Entfernen von Elementen:
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 2; }
Beispiel für den falschen Ansatz:
while (my ($k, $v) = each %h) { delete $h{$k}; # Das kann zum Überspringen von Schlüsseln führen }
Wesentliche Merkmale:
Kann man sicher Elemente aus einem Hash innerhalb einer while-Schleife (each %h) entfernen?
Nein, das kann dazu führen, dass Teile des Hashs aufgrund des Zurücksetzens des internen Iterationszeigers übersprungen werden.
Was passiert mit der Reihenfolge der Schlüssel nach dem Entfernen von Elementen aus einem Hash?
Die Reihenfolge ist nicht garantiert und kann sich ändern. Zudem kann die Reihenfolge der Durchquerung zwischen Programmen mit identischem Perl unterschiedlich sein.
Kann man den Wert eines Hash-Elements innerhalb der Iteration durch each ändern?
Ja, die Änderung des Wertes (aber nicht der Struktur) ist sicher.
Beispiel:
while (my ($k, $v) = each %h) { $h{$k} = $v + 10; }
Verwendung des Entfernens von Elementen über each in einer Schleife:
my %h = (a=>1, b=>2, c=>3); while (my ($k, $v) = each %h) { delete $h{$k} if $v == 1; }
Vorteile:
Nachteile:
Erstellung einer Schlüsselliste zum Löschen:
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 1; }
Vorteile:
Nachteile: