En Perl, les hachages (tableaux associatifs) sont un outil puissant pour stocker des paires clé-valeur. Cependant, travailler avec eux nécessite de l'attention, surtout lors de l'itération et de la modification simultanée de leur structure. Des détails manquants peuvent conduire à des erreurs difficiles à diagnostiquer.
Les tableaux associatifs ont été introduits dans les premières versions de Perl (Perl 1/2), ce qui en a fait l'un des premiers langages à prendre en charge les hachages à un niveau fondamental. Avec le temps, des fonctionnalités supplémentaires ont été ajoutées : l'itération via each, la suppression (delete), la transformation massive (map, grep) et la gestion des modifications de taille/contenu pendant l'itération.
L'itération sur un hachage et la modification simultanée de son contenu, en particulier la suppression d'éléments, peuvent mener à des effets inattendus : des éléments manquants, des passages répétés sur les mêmes clés, ou même une boucle infinie. De plus, l'ordre d'itération des clés n'est pas garanti et peut changer entre les versions de Perl.
each, car le curseur interne est perturbé.keys, puis itérez dessus dans une boucle séparée pour les supprimer.while (my ($k, $v) = each %h) pour une itération standard, mais ne combinez pas avec delete à l'intérieur de la boucle si vous ne voulez pas d'imprévus.Exemple de suppression correcte d'éléments :
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 2; }
Exemple d'approche incorrecte :
while (my ($k, $v) = each %h) { delete $h{$k}; # Cela peut conduire à des clés manquantes }
Caractéristiques clés :
Peut-on supprimer en toute sécurité des éléments d'un hachage à l'intérieur d'une boucle while (each %h) ?
Non, cela peut entraîner le saut de parties du hachage en raison du réinitialisation du curseur d'itération interne.
Que se passe-t-il avec l'ordre des clés après la suppression d'éléments du hachage ?
L'ordre n'est pas garanti et peut changer. De plus, l'ordre d'itération entre les programmes utilisant le même Perl peut différer.
Peut-on changer la valeur d'un élément d'un hachage pendant l'itération via each ?
Oui, la modification de la valeur (mais pas de la structure) est sûre.
Exemple :
while (my ($k, $v) = each %h) { $h{$k} = $v + 10; }
Utilisation de la suppression d'éléments via each dans une même boucle :
my %h = (a=>1, b=>2, c=>3); while (my ($k, $v) = each %h) { delete $h{$k} if $v == 1; }
Avantages :
Inconvénients :
Création d'une liste de clés pour suppression :
my %h = (a=>1, b=>2, c=>3); for my $k (keys %h) { delete $h{$k} if $h{$k} == 1; }
Avantages :
Inconvénients :