Quelle est la meilleure implémentation (en termes de vitesse et d'utilisation de la mémoire) pour itérer dans un tableau Perl? Y a-t-il une meilleure façon? ( @Array
ne doit pas être conservé).
Mise en œuvre 1
foreach (@Array)
{
SubRoutine($_);
}
Mise en œuvre 2
while($Element=shift(@Array))
{
SubRoutine($Element);
}
Mise en œuvre 3
while(scalar(@Array) !=0)
{
$Element=shift(@Array);
SubRoutine($Element);
}
Mise en œuvre 4
for my $i (0 .. $#Array)
{
SubRoutine($Array[$i]);
}
Mise en œuvre 5
map { SubRoutine($_) } @Array ;
map
une réponse acceptable ?. etc.)Réponses:
En termes de vitesse: # 1 et # 4, mais pas de beaucoup dans la plupart des cas.
Vous pourriez écrire un benchmark pour confirmer, mais je suppose que vous trouverez que les n ° 1 et 4 sont légèrement plus rapides car le travail d'itération est effectué en C au lieu de Perl, et aucune copie inutile des éléments du tableau ne se produit. (
$_
est aliasé sur l'élément dans # 1, mais # 2 et # 3 copient en fait les scalaires du tableau.)# 5 pourrait être similaire.
En termes d'utilisation de la mémoire: ils sont tous les mêmes sauf pour # 5.
for (@a)
est un boîtier spécial pour éviter d'aplatir le tableau. La boucle itère sur les index du tableau.En termes de lisibilité: # 1.
En termes de flexibilité: # 1 / # 4 et # 5.
# 2 ne prend pas en charge les éléments qui sont faux. Les n ° 2 et 3 sont destructeurs.
la source
my @todo = $root; while (@todo) { my $node = shift; ...; push @todo, ...; ...; }
Si vous ne vous souciez que des éléments de
@Array
, utilisez:ou
Si les indices comptent, utilisez:
Ou, à partir de la version
perl
5.12.1, vous pouvez utiliser:Si vous avez besoin à la fois de l'élément et de son index dans le corps de la boucle,
Je m'attendraisen utilisanteach
être le plus rapide, mais alorsvous renoncerez à la compatibilité avec les versions antérieures à 5.12.1perl
.Un autre modèle que ceux-ci pourrait être approprié dans certaines circonstances.
la source
each
à ce que ce soit le plus lent. Il fait tout le travail des autres moins un alias, plus une affectation de liste, deux copies scalaires et deux effacements scalaires.for
itération sur les indices d'un tableau, et 20% plus rapide lors de l'itération sur les index d'une référence de tableau (j'accède$array->[$i]
dans le corps), sur l'utilisationeach
en conjonction avecwhile
.IMO, la mise en œuvre n ° 1 est typique et étant courte et idiomatique pour Perl l'emporte sur les autres pour cela seul. Un benchmark des trois choix pourrait vous offrir au moins un aperçu de la vitesse.
la source
1 est sensiblement différent de 2 et 3, car il laisse le réseau intact, tandis que les deux autres le laissent vide.
Je dirais que le n ° 3 est assez farfelu et probablement moins efficace, alors oubliez cela.
Ce qui vous laisse avec le n ° 1 et le n ° 2, et ils ne font pas la même chose, donc l'un ne peut pas être "meilleur" que l'autre. Si le tableau est volumineux et que vous n'avez pas besoin de le conserver, la portée le traitera généralement ( mais voir NOTE ), donc généralement , # 1 est toujours la méthode la plus claire et la plus simple. Décaler chaque élément n'accélérera rien. Même s'il est nécessaire de libérer le tableau de la référence, j'irais simplement:
lorsque vous avez terminé.
la source
@Array = ();
ne libère pas le tableau sous-jacent. Ne même pas sortir du champ de vision ferait cela. Si vous vouliez libérer le tableau sous-jacent, vous auriez utiliséundef @Array;
.perl -MDevel::Peek -e'my @a; Dump(\@a,1); @a=qw( a b c ); Dump(\@a,1); @a=(); Dump(\@a,1); undef @a; Dump(\@a,1);' 2>&1 | grep ARRAY
()
vsundef
, mais si sortir de la portée ne libère pas la mémoire utilisée par un tableau local dans cette portée, cela ne fait-il pas de Perl un désastre de fuite? Cela ne peut pas être vrai.En une seule ligne pour imprimer l'élément ou le tableau.
print $ _ pour (@array);
NOTE: rappelez-vous que $ _ fait référence en interne à l'élément de @array en boucle. Toutes les modifications apportées à $ _ seront reflétées dans @array; ex.
sortie: 2 4 6
la source
La meilleure façon de décider de questions comme celle-ci pour les comparer:
Et l'exécuter sur perl 5, version 24, subversion 1 (v5.24.1) construit pour x86_64-linux-gnu-thread-multi
Je reçois:
Ainsi, le 'foreach (@Array)' est environ deux fois plus rapide que les autres. Tous les autres sont très similaires.
@ikegami souligne également qu'il existe de nombreuses différences dans ces implémentations autres que la vitesse.
la source
$index < $#array
devrait en fait être$index <= $#array
car ce$#array
n'est pas la longueur du tableau mais le dernier index de celui-ci.