La règle de base est d'utiliser la fonction la plus adaptée à vos besoins.
Si vous voulez juste les clés et ne prévoyez jamais de lire aucune des valeurs, utilisez keys ():
foreach my $key (keys %hash) { ... }
Si vous voulez juste les valeurs, utilisez values ():
foreach my $val (values %hash) { ... }
Si vous avez besoin des clés et des valeurs, utilisez each ():
keys %hash; # reset the internal iterator so a prior each() doesn't affect the loop
while(my($k, $v) = each %hash) { ... }
Si vous envisagez de modifier les clés du hachage de quelque manière que ce soit, sauf pour supprimer la clé actuelle pendant l'itération, vous ne devez pas utiliser each (). Par exemple, ce code pour créer un nouvel ensemble de clés majuscules avec des valeurs doublées fonctionne très bien en utilisant keys ():
%h = (a => 1, b => 2);
foreach my $k (keys %h)
{
$h{uc $k} = $h{$k} * 2;
}
produire le hachage résultant attendu:
(a => 1, A => 2, b => 2, B => 4)
Mais en utilisant each () pour faire la même chose:
%h = (a => 1, b => 2);
keys %h;
while(my($k, $v) = each %h)
{
$h{uc $k} = $h{$k} * 2; # BAD IDEA!
}
produit des résultats incorrects de manière difficile à prévoir. Par exemple:
(a => 1, A => 2, b => 2, B => 8)
Ceci, cependant, est sûr:
keys %h;
while(my($k, $v) = each %h)
{
if(...)
{
delete $h{$k}; # This is safe
}
}
Tout cela est décrit dans la documentation perl:
% perldoc -f keys
% perldoc -f each
Une chose dont vous devez être conscient lors de l'utilisation
each
est que cela a pour effet secondaire d'ajouter un "état" à votre hachage (le hachage doit se souvenir de ce qu'est la clé "suivante"). Lorsque vous utilisez du code comme les extraits publiés ci-dessus, qui itèrent sur tout le hachage en une seule fois, ce n'est généralement pas un problème. Cependant, vous rencontrerez des problèmes difficiles à localiser (je parle d'expérience;), lors de l'utilisationeach
avec des instructions commelast
oureturn
pour sortir de lawhile ... each
boucle avant d'avoir traité toutes les clés.Dans ce cas, le hachage se souviendra des clés qu'il a déjà renvoyées, et lorsque vous l'utiliserez
each
la prochaine fois (peut-être dans un morceau de code totalement indépendant), il continuera à cette position.Exemple:
Cela imprime:
Qu'est-il arrivé aux touches "bar" et baz "? Elles sont toujours là, mais la seconde
each
commence là où la première s'est arrêtée et s'arrête quand elle atteint la fin du hachage, donc on ne les voit jamais dans la seconde boucle.la source
L'endroit où cela
each
peut vous causer des problèmes est qu'il s'agit d'un véritable itérateur sans portée. A titre d'exemple:Si vous avez besoin d'être sûr que
each
toutes les clés et valeurs sont obtenues, vous devez vous assurer que vous utilisezkeys
ou d'values
abord (car cela réinitialise l'itérateur). Consultez la documentation de chacun .la source
L'utilisation de chaque syntaxe empêchera la génération de l'ensemble de clés en même temps. Cela peut être important si vous utilisez un hachage lié à une base de données avec des millions de lignes. Vous ne voulez pas générer la liste complète des clés en une seule fois et épuiser votre mémoire physique. Dans ce cas, chacun sert d'itérateur alors que les clés génèrent en fait le tableau entier avant le début de la boucle.
Ainsi, le seul endroit où «chacun» est réellement utile est lorsque le hachage est très important (par rapport à la mémoire disponible). Cela ne se produira probablement que lorsque le hachage lui-même ne vit pas dans la mémoire elle-même, à moins que vous ne programmiez un appareil de collecte de données portable ou quelque chose avec une petite mémoire.
Si la mémoire n'est pas un problème, le paradigme de la carte ou des clés est généralement le paradigme le plus important et le plus facile à lire.
la source
Quelques réflexions diverses sur ce sujet:
values
auquel je puisse penser est que les alias retournent, ce qui signifie que leur modification modifiera le contenu du hachage. C'est par conception, mais peut ne pas être ce que vous voulez dans certaines circonstances.each
. Ceci est pas vrai pourkeys
queeach
est un itérateur toutkeys
retourne une liste.la source
J'utilise toujours aussi la méthode 2. Le seul avantage de l'utilisation de chacun est que si vous lisez simplement (plutôt que de réattribuer) la valeur de l'entrée de hachage, vous ne dé-référencerez pas constamment le hachage.
la source
Je peux me faire mordre par celui-ci mais je pense que c'est une préférence personnelle. Je ne trouve aucune référence dans la documentation indiquant que chaque () est différent de keys () ou values () (autre que la réponse évidente "ils renvoient des choses différentes". En fait, la documentation déclare utiliser le même itérateur et ils renvoie des valeurs de liste réelles au lieu de copies de celles-ci, et que modifier le hachage en l'itérant à l'aide d'un appel est mauvais.
Cela dit, j'utilise presque toujours keys () car pour moi, il est généralement plus auto-documenté d'accéder à la valeur de la clé via le hachage lui-même. J'utilise parfois values () lorsque la valeur est une référence à une grande structure et que la clé du hachage était déjà stockée dans la structure, à quel point la clé est redondante et je n'en ai pas besoin. Je pense que j'ai utilisé each () 2 fois en 10 ans de programmation Perl et c'était probablement le mauvais choix les deux fois =)
la source
J'utilise habituellement
keys
et je ne peux pas penser à la dernière fois que j'ai utilisé ou lu une utilisation deeach
.N'oubliez pas
map
, en fonction de ce que vous faites dans la boucle!la source
Je dirais:
Cela donne 2 avantages majeurs:
Je ne pense pas qu'il soit plus coûteux d'utiliser des clés sur chacune, donc pas besoin de deux constructions différentes pour la même chose dans votre code.
la source
keys
utilisation de la mémoire augmente dehash-size * avg-key-size
. Étant donné que la taille de la clé n'est limitée que par la mémoire (car ce ne sont que des éléments de tableau comme «leurs» valeurs correspondantes sous le capot), dans certaines situations, cela peut être prohibitif en termes d'utilisation de la mémoire et de temps nécessaire pour faire la copie.