撒拉嘿哟木头
2012-05-07 18:43
采纳率: 40%
浏览 329

迭代 Perl 数组的最佳方法

Which is the best implementation(in terms of speed and memory usage) for iterating through a Perl array? Is there any better way? (@Array need not be retained).

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 ;

转载于:https://stackoverflow.com/questions/10487316/best-way-to-iterate-through-a-perl-array

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

6条回答 默认 最新

  • ?yb? 2012-05-07 20:00
    已采纳
    • In terms of speed: #1 and #4, but not by much in most instances.

      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.

    点赞 评论
  • hurriedly% 2012-05-07 19:01

    1 is substantially different from 2 and 3, since it leaves the array in tact, whereas the other two leave it empty.

    I'd say #3 is pretty wacky and probably less efficient, so forget that.

    Which leaves you with #1 and #2, and they do not do the same thing, so one cannot be "better" than the other. If the array is large and you don't need to keep it, generally scope will deal with it (but see NOTE), so generally, #1 is still the clearest and simplest method. Shifting each element off will not speed anything up. Even if there is a need to free the array from the reference, I'd just go:

    undef @Array;
    

    when done.

    • 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).
    点赞 评论
  • from.. 2012-05-07 19:03

    IMO, implementation #1 is typical and being short and idiomatic for Perl trumps the others for that alone. A benchmark of the three choices might offer you insight into speed, at least.

    点赞 评论
  • larry*wei 2012-05-07 23:19

    If you only care about the elements of @Array, use:

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

    or

    If the indices matter, use:

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

    Or, as of perl 5.12.1, you can use:

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

    If you need both the element and its index in the body of the loop, I would expect using each to be the fastest, but then you'll be giving up compatibility with pre-5.12.1 perls.

    Some other pattern than these might be appropriate under certain circumstances.

    点赞 评论
  • MAO-EYE 2017-03-30 09:09

    In single line to print the element or array.

    print $_ for (@array);

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

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

    output: 2 4 6

    点赞 评论
  • ℙℕℤℝ 2018-02-01 11:53

    The best way to decide questions like this to benchmark them:

    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,
    });
    

    And running this on perl 5, version 24, subversion 1 (v5.24.1) built for x86_64-linux-gnu-thread-multi

    I get:

    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)
    

    So the 'foreach (@Array)' is about twice as fast as the others. All the others are very similar.

    @ikegami also points out that there are quite a few differences in these implimentations other than speed.

    点赞 评论

相关推荐 更多相似问题