Вопрос по perl, arrays – Лучший способ перебрать массив Perl

89

Error: User Rate Limit Exceeded@ArrayError: User Rate Limit Exceeded

Implementation 1

foreach (@Array)
{
      SubRoutine($_);
}

Implementation 2

while($Element=shift(@Array))
{
      SubRoutine($Element);
}

Implementation 3

while(scalar(@Array) !=0)
{
      $Element=shift(@Array);
      SubRoutine($Element);
}

Implementation 4

for my $i (0 .. $#Array)
{
      SubRoutine($Array[$i]);
}

Implementation 5

map { SubRoutine($_) } @Array ;
Error: User Rate Limit Exceeded user289086
Error: User Rate Limit Exceeded workwise
Error: User Rate Limit ExceededWhat's the best way to add two numbers?Error: User Rate Limit Exceeded Sinan Ünür
Error: User Rate Limit ExceededmapError: User Rate Limit Exceeded Max Lybbert
Error: User Rate Limit ExceededbutError: User Rate Limit Exceeded delicateLatticeworkFever

Ваш Ответ

6   ответов
69

You could write a benchmark to confirm, but I suspect you'll find #1 and #4 to be slightly faster because the iteration work is done in C instead of Perl, and no needless copying of the array elements occurs. ($_ is aliased to the element in #1, but #2 and #3 actually copy the scalars from the array.)

#5 might be similar.

In terms memory usage: They're all the same except for #5.

for (@a) is special-cased to avoid flattening the array. The loop iterates over the indexes of the array.

In terms of readability: #1.

In terms of flexibility: #1/#4 and #5.

#2 does not support elements that are false. #2 and #3 are destructive.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededmy @todo = $root; while (@todo) { my $node = shift; ...; push @todo, ...; ...; }
0

use strict;
use warnings;
use Benchmark qw(:all);

our @input_array = (0..1000);

my $a = sub {
    my @array = @{[ @input_array ]};
    my $index = 0;
    foreach my $element (@array) {
       die unless $index == $element;
       $index++;
    }
};

my $b = sub {
    my @array = @{[ @input_array ]};
    my $index = 0;
    while (defined(my $element = shift @array)) {
       die unless $index == $element;
       $index++;
    }
};

my $c = sub {
    my @array = @{[ @input_array ]};
    my $index = 0;
    while (scalar(@array) !=0) {
       my $element = shift(@array);
       die unless $index == $element;
       $index++;
    }
};

my $d = sub {
    my @array = @{[ @input_array ]};
    foreach my $index (0.. $#array) {
       my $element = $array[$index];
       die unless $index == $element;
    }
};

my $e = sub {
    my @array = @{[ @input_array ]};
    for (my $index = 0; $index < $#array; $index++) {
       my $element = $array[$index];
       die unless $index == $element;
    }
};

my $f = sub {
    my @array = @{[ @input_array ]};
    while (my ($index, $element) = each @array) {
       die unless $index == $element;
    }
};

my $count;
timethese($count, {
   '1' => $a,
   '2' => $b,
   '3' => $c,
   '4' => $d,
   '5' => $e,
   '6' => $f,
});

Benchmark: running 1, 2, 3, 4, 5, 6 for at least 3 CPU seconds...
         1:  3 wallclock secs ( 3.16 usr +  0.00 sys =  3.16 CPU) @ 12560.13/s (n=39690)
         2:  3 wallclock secs ( 3.18 usr +  0.00 sys =  3.18 CPU) @ 7828.30/s (n=24894)
         3:  3 wallclock secs ( 3.23 usr +  0.00 sys =  3.23 CPU) @ 6763.47/s (n=21846)
         4:  4 wallclock secs ( 3.15 usr +  0.00 sys =  3.15 CPU) @ 9596.83/s (n=30230)
         5:  4 wallclock secs ( 3.20 usr +  0.00 sys =  3.20 CPU) @ 6826.88/s (n=21846)
         6:  3 wallclock secs ( 3.12 usr +  0.00 sys =  3.12 CPU) @ 5653.53/s (n=17639)

0

NOTE: remember that $_ is internally referring to the element of @array in loop. Any changes made in $_ will reflect in @array;

my @array = qw( 1 2 3 );
for (@array) {
        $_ = $_ *2 ;
}
print "@array";

23

Error: User Rate Limit Exceeded@ArrayError: User Rate Limit Exceeded

for my $el (@Array) {
# ...
}

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

for my $i (0 .. $#Array) {
# ...
}

Error: User Rate Limit ExceededperlError: User Rate Limit Exceeded

while (my ($i, $el) = each @Array) {
# ...
}

Error: User Rate Limit ExceededI would expectError: User Rate Limit Exceededeach to be the fastest, but thenError: User Rate Limit ExceededperlError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededforError: User Rate Limit Exceeded$array->[$i]Error: User Rate Limit ExceededeachError: User Rate Limit Exceededwhile.
Error: User Rate Limit ExceededeachError: User Rate Limit Exceeded
2

generallybut see NOTE,generally

undef @Array;

NOTE: The subroutine containing the scope of the array actually keeps the array and re-uses the space next time. Generally, that should be fine (see comments).
Error: User Rate Limit Exceededperl -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
WHAT???Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded()Error: User Rate Limit ExceededundefError: User Rate Limit Exceededcan'tError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
@Array = ();Error: User Rate Limit Exceededundef @Array;.
3

Похожие вопросы