最好的方式来通过一个Perl阵列迭代(Best way to iterate through a P

2019-06-24 05:50发布

这是通过一个Perl数组迭代最好的实现(在速度和内存使用方面)? 有没有更好的办法? ( @Array不必保留)。

实施1

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

实施2

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

实施3

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

实施4

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

实施5

map { SubRoutine($_) } @Array ;

Answer 1:

  • 在速度方面:#1和#4,但不是很多在大多数情况下。

    你可以写一个基准来确定,但我怀疑你会发现#1和#4,因为迭代工作是用C代替的Perl和数组元素的无不必要的复制发生时要稍快一些。 ( $_别名设置在#1的元件,但#2和#3的实际标量从阵列复制 。)

    #5可能是相似的。

  • 在条件内存使用情况:他们除了5号都是一样的。

    for (@a)是特例,以避免平坦化阵列。 所述循环迭代数组的索引。

  • 在可读性方面:#1。

  • 在灵活性方面:#1 /#4和#5。

    #2不支持任何虚假元素。 #2和#3是破坏性的。



Answer 2:

如果你只关心的元素@Array ,使用方法:

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

要么

如果指数关系,使用方法:

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

或者,作为perl 5.12.1,您可以使用:

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

如果您同时需要元素及其指数的循环体, 我期望 利用each 是最快的,但随后 你会放弃兼容5.12.1前perl秒。

其他一些模式比这些可能是在某些情况下适当的。



Answer 3:

IMO,实现#1是典型的做空和习惯为Perl胜过别人,单靠。 这三个选项的基准可能会为您提供洞察速度,至少。



Answer 4:

图1是从图2和3基本上不同,因为它的叶子在间歇阵列,而其它两个保留空白。

我会说#3是很古怪,可能效率较低,所以忘了。

这让你#1和#2,和他们不这样做同样的事情,因此不能比其他“更好”。 如果数组很大,你并不需要保留它, 一般范围将处理它( 但是见 ),所以一般 ,#1仍然是最清晰,最简单的方法。 移动每个元素断不会加速任何东西。 即使有必要摆脱参考阵列,我只是去:

undef @Array;

当完成。

  • :包含数组的范围子程序实际上保持阵列和重新使用的空间下一次。 一般情况下 ,这应该是罚款(见注释)。


Answer 5:

在单线打印元件或阵列。

打印$ _的(@array);

注:请记住,$ _内部参考@array的环路的元素。 在$ _将@array反映所做的任何更改; 恩。

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

输出:2 4 6



Answer 6:

确定这样的问题来作为比较基准的最佳方式:

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

而对x86_64的Linux的GNU的线程多建的Perl 5,24版,颠覆1(v5.24.1)运行此

我得到:

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)

所以“的foreach(@array)”的两倍左右的速度是其他。 所有的人都非常相似。

@ikegami还指出,目前在比速度等这些implimentations不少差异。



文章来源: Best way to iterate through a Perl array