In Perl gibt es mehrere Möglichkeiten, um über Hashes zu iterieren: über each, über die Liste der Schlüssel (keys) und foreach, sowie über values. Von Anfang an war vorgesehen, dass Hashes für den schnellen Zugriff auf Daten verwendet werden, daher wurden die Iterationsmethoden unter Berücksichtigung der Leistung und der Minimierung der zusätzlichen Speicherzuweisung entwickelt.
Problem: Bei der Verwendung dieser Techniken gibt es viele Fallstricke: die Veränderung des Hashes während der Iteration, das Speichern des Iterators, die Reihenfolge der Elemente, die Nebenwirkungen von each auf den Hash sowie das Risiko unerwarteten Verhaltens bei verschachtelter Iteration.
Lösung: Für eine sichere und vorhersehbare Iteration wird empfohlen, foreach my $key (sort keys %hash) zu verwenden, den Hash während der Iteration nicht zu modifizieren und für each den Iterator immer mit keys %hash vor einer neuen Schleife zurückzusetzen.
Beispielcode:
my %hash = ( a => 1, b => 2, c => 3 ); foreach my $key (sort keys %hash) { print "$key: $hash{$key} "; # Vorhersehbare Reihenfolge }
Schlüsselmerkmale:
keys gibt eine Kopie der Schlüsselliste zurück, die Reihenfolge ist nicht definiert.each wird für den Hash gespeichert, mehrere Schleifen gleichzeitig sind nur mit verschiedenen Hashes möglich.each-Iterator zurückzusetzen, wird ein leerer Aufruf von keys verwendet.Kann man den Hash während der Iteration über each sicher ändern?
Nein, das führt zu unkontrollierbaren Folgen: Daten können ausgelassen oder mehrfach gezählt werden.
Wenn man each für zwei verschiedene Hashes aufruft, wird es einen gemeinsamen Iterator geben?
Nein, die Iteratoren sind unabhängig für jeden Hash.
Kann man zwei Schleifen über each für denselben Hash verschachteln?
Nein, der Iterator wird "verwirrt" und die Ergebnisse werden unvorhersehbar sein. Für solche Fälle sollte man keys und verschachtelte Schleifen verwenden.
Die Verwendung von each zur Iteration über einen Hash in einer Funktion, die mehrmals mit unterschiedlichen Teilen desselben Hashes aufgerufen wird. Der Iterator wird verwirrt, ein Teil der Daten geht verloren.
Vorteile:
Nachteile:
Die Verwendung von foreach und keys zur Iteration, vollständige Durchmusterung mit expliziter Speicherung der Schlüssel in einem separaten Array.
Vorteile:
Nachteile: