Als Faustregel gilt, die Funktion zu verwenden, die Ihren Anforderungen am besten entspricht.
Wenn Sie nur die Schlüssel möchten und nicht vorhaben, jemals einen der Werte zu lesen , verwenden Sie keys ():
foreach my $key (keys %hash) { ... }
Wenn Sie nur die Werte möchten, verwenden Sie values ():
foreach my $val (values %hash) { ... }
Wenn Sie die Schlüssel und Werte benötigen , verwenden Sie each ():
keys %hash; # reset the internal iterator so a prior each() doesn't affect the loop
while(my($k, $v) = each %hash) { ... }
Wenn Sie vorhaben, die Schlüssel des Hashs in irgendeiner Weise zu ändern, außer den aktuellen Schlüssel während der Iteration zu löschen, dürfen Sie nicht jeden () verwenden. Dieser Code zum Erstellen eines neuen Satzes von Großbuchstaben mit doppelten Werten funktioniert beispielsweise mit keys ():
%h = (a => 1, b => 2);
foreach my $k (keys %h)
{
$h{uc $k} = $h{$k} * 2;
}
Erzeugen des erwarteten resultierenden Hash:
(a => 1, A => 2, b => 2, B => 4)
Aber mit jedem () das Gleiche tun:
%h = (a => 1, b => 2);
keys %h;
while(my($k, $v) = each %h)
{
$h{uc $k} = $h{$k} * 2; # BAD IDEA!
}
führt auf schwer vorhersehbare Weise zu falschen Ergebnissen. Beispielsweise:
(a => 1, A => 2, b => 2, B => 8)
Dies ist jedoch sicher:
keys %h;
while(my($k, $v) = each %h)
{
if(...)
{
delete $h{$k}; # This is safe
}
}
All dies ist in der Perl-Dokumentation beschrieben:
% perldoc -f keys
% perldoc -f each
Eine Sache, die Sie bei der Verwendung beachten sollten,
each
ist, dass sie den Nebeneffekt hat, Ihrem Hash "state" hinzuzufügen (der Hash muss sich merken, was der "nächste" Schlüssel ist). Wenn Sie Code wie die oben angegebenen Snippets verwenden, die den gesamten Hash auf einmal durchlaufen, ist dies normalerweise kein Problem. Es wird jedoch schwierig sein, Probleme aufzuspüren (ich spreche aus Erfahrung;), wenn Sieeach
zusammen mit Anweisungen wielast
oderreturn
diewhile ... each
Schleife verlassen, bevor Sie alle Schlüssel verarbeitet haben.In diesem Fall merkt sich der Hash, welche Schlüssel er bereits zurückgegeben hat, und wenn Sie
each
ihn das nächste Mal verwenden (möglicherweise in einem völlig unabhängigen Code), wird er an dieser Position fortgesetzt.Beispiel:
Dies druckt:
Was ist mit den Tasten "bar" und "baz" passiert? Sie sind immer noch da, aber die zweite
each
beginnt dort, wo die erste aufgehört hat, und endet, wenn sie das Ende des Hashs erreicht, sodass wir sie in der zweiten Schleife nie sehen.quelle
Der Ort, an dem
each
Sie Probleme verursachen können, ist, dass es sich um einen echten Iterator ohne Gültigkeitsbereich handelt. Als Beispiel:Wenn Sie sicherstellen müssen, dass
each
alle Schlüssel und Werte abgerufen werden, müssen Sie sicherstellen, dass Siekeys
odervalues
zuerst verwenden (da dies den Iterator zurücksetzt). Siehe jeweils die Dokumentation .quelle
Durch die Verwendung der einzelnen Syntax wird verhindert, dass der gesamte Schlüsselsatz auf einmal generiert wird. Dies kann wichtig sein, wenn Sie einen verknüpften Hash an eine Datenbank mit Millionen von Zeilen verwenden. Sie möchten nicht die gesamte Liste der Schlüssel auf einmal generieren und Ihren physischen Speicher erschöpfen. In diesem Fall dient jeder als Iterator, während Schlüssel tatsächlich das gesamte Array generieren, bevor die Schleife beginnt.
Der einzige Ort, an dem "jeder" wirklich von Nutzen ist, ist, wenn der Hash sehr groß ist (im Vergleich zum verfügbaren Speicher). Dies ist nur dann wahrscheinlich, wenn der Hash selbst nicht im Speicher selbst gespeichert ist, es sei denn, Sie programmieren ein Handheld-Datenerfassungsgerät oder etwas mit kleinem Speicher.
Wenn das Gedächtnis kein Problem darstellt, ist normalerweise das Karten- oder Schlüsselparadigma das umfassendere und leichter zu lesende Paradigma.
quelle
Einige verschiedene Gedanken zu diesem Thema:
values
vorstellen kann, ist, dass Aliase zurückgegeben werden, was bedeutet, dass durch Ändern der Werte der Inhalt des Hashs geändert wird. Dies ist beabsichtigt, kann aber unter bestimmten Umständen nicht das sein, was Sie wollen.each
. Das ist nicht wahr fürkeys
soeach
ist ein Iterator währendkeys
kehrt eine Liste.quelle
Ich benutze immer auch Methode 2. Der einzige Vorteil der Verwendung ist, dass Sie den Hash nicht ständig de-referenzieren, wenn Sie nur den Wert des Hash-Eintrags lesen (anstatt ihn neu zuzuweisen).
quelle
Ich werde vielleicht von diesem gebissen, aber ich denke, dass es eine persönliche Präferenz ist. Ich kann in den Dokumenten keinen Verweis darauf finden, dass sich jedes () von den Schlüsseln () oder Werten () unterscheidet (abgesehen von der offensichtlichen Antwort "Sie geben verschiedene Dinge zurück"). Tatsächlich geben die Dokumente an, dass derselbe Iterator und alle verwendet werden Geben Sie tatsächliche Listenwerte anstelle von Kopien davon zurück, und es ist schlecht, den Hash zu ändern, während Sie ihn mit einem beliebigen Aufruf durchlaufen.
Trotzdem verwende ich fast immer keys (), da es für mich normalerweise selbstdokumentierender ist, über den Hash selbst auf den Wert des Schlüssels zuzugreifen. Ich verwende gelegentlich values (), wenn der Wert auf eine große Struktur verweist und der Schlüssel zum Hash bereits in der Struktur gespeichert war. Zu diesem Zeitpunkt ist der Schlüssel redundant und ich brauche ihn nicht. Ich glaube, ich habe in 10 Jahren Perl-Programmierung jedes () 2 Mal verwendet und es war wahrscheinlich beide Male die falsche Wahl =)
quelle
Normalerweise benutze
keys
ich und ich kann mir nicht vorstellen, wann ich das letzte Mal benutzt oder gelesen habeeach
.Vergessen Sie nicht
map
, je nachdem, was Sie in der Schleife tun!quelle
Ich würde sagen:
Dies ergibt 2 Hauptvorteile:
Ich denke nicht, dass es teurer ist, Schlüssel über jedem zu verwenden, so dass Sie nicht zwei verschiedene Konstrukte für dasselbe in Ihrem Code benötigen.
quelle
keys
Speichernutzung steigt umhash-size * avg-key-size
. Da die Schlüsselgröße nur durch den Speicher begrenzt ist (da es sich lediglich um Array-Elemente wie "ihre" entsprechenden Werte unter der Haube handelt), kann dies in einigen Situationen sowohl bei der Speichernutzung als auch bei der Erstellung der Kopie unerschwinglich sein .