Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 遍历Perl数组的最佳方法_Arrays_Perl_Iteration - Fatal编程技术网

Arrays 遍历Perl数组的最佳方法

Arrays 遍历Perl数组的最佳方法,arrays,perl,iteration,Arrays,Perl,Iteration,在速度和内存使用方面,迭代Perl数组的最佳实现是什么?还有更好的办法吗?(@Array无需保留) 实施1 实施2 执行情况3 执行情况4 执行情况5 1与2和3有本质上的不同,因为它使数组保持不变,而其他两个使数组保持为空 我得说#3相当古怪,效率可能更低,所以别提了 这就给你留下了#1和#2,它们做的事情不一样,所以一个不能比另一个“更好”。如果数组很大,您不需要保留它,则scope通常会处理它(但请参见注意),因此一般来说,#1仍然是最清晰、最简单的方法。关闭每个元件不会加快任何速度。即使

在速度和内存使用方面,迭代Perl数组的最佳实现是什么?还有更好的办法吗?(
@Array
无需保留)

实施1 实施2 执行情况3 执行情况4 执行情况5
1与2和3有本质上的不同,因为它使数组保持不变,而其他两个使数组保持为空

我得说#3相当古怪,效率可能更低,所以别提了

这就给你留下了#1和#2,它们做的事情不一样,所以一个不能比另一个“更好”。如果数组很大,您不需要保留它,则scope通常会处理它(但请参见注意),因此一般来说,#1仍然是最清晰、最简单的方法。关闭每个元件不会加快任何速度。即使需要将数组从引用中释放出来,我也会:

undef @Array;
完成后

  • 注意:包含数组范围的子例程实际上保留了数组,并在下次重新使用该空间。一般来说,这应该没问题(见评论)
在我看来,实现1是典型的,而且对于Perl来说,它是简短和惯用的,这一点就胜过了其他的实现。至少,这三种选择的基准可以让你洞察速度。

  • 就速度而言:#1和#4,但在大多数情况下并不多

    您可以编写一个基准来确认,但我怀疑您会发现#1和#4稍微快一点,因为迭代工作是用C而不是Perl完成的,并且不会发生不必要的数组元素复制。(
    $
    别名为#1中的元素,但#2和#3实际上从数组中复制了标量。)

    #5可能是相似的

  • 在内存使用方面:除了#5之外,它们都是相同的

    (@a)的
    是特殊情况,以避免阵列扁平化。循环遍历数组的索引

  • 在可读性方面:#1

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

    #2不支持为false的元素#2和#3具有破坏性


如果您只关心
@Array
的元素,请使用:

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

如果指数重要,请使用:

for my $i (0 .. $#Array) {
# ...
}
或者,从
perl
5.12.1开始,您可以使用:

while (my ($i, $el) = each @Array) {
# ...
}
如果您需要在循环体中同时使用元素及其索引,我希望使用
每个
都是最快的,但是您将放弃与5.12.1之前的
perl
s的兼容性


在某些情况下,除此之外的其他一些图案可能是合适的。

在单行中打印元素或数组

打印(@array)的$uu

注意:请记住,$\在内部是指循环中@array的元素。美元的任何更改都将反映在@array中


输出:2 4 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,
});
因此,“foreach(@Array)”的速度大约是其他的两倍。其他的都很相似


@ikegami还指出,除了速度之外,这些实现还有很多不同之处。

为什么会有“最佳”呢?特别是考虑到我们不知道你会如何衡量彼此(速度比内存使用更重要吗?
map
和可接受的答案?等等),你发布的三个选项中的两个会让我去“WTH?!”,除非有额外的周围环境使它们成为明智的选择。在任何情况下,这个问题都处于“添加两个数字的最佳方式是什么?”的水平,大多数情况下,只有一种方式。然后,在这些情况下,你需要一种不同的方式。投票结束。@SinanÜnür我同意你的观点(只有一种方法可以将两个数字相加),但这个类比不够有力,不能轻蔑地使用。显然,有不止一种方法,OP希望了解什么是好主意,什么不是。Perl编程第三版第24章有一节是关于效率的,这是一本很好的书。它解决了不同类型的效率,如时间、程序员、维护人员。本节以“请注意,时间优化有时可能会降低您的空间或程序员效率(由下面冲突的提示指示)。这就是中断”这句话开始。添加两个数字的一种方法?如果您查看较低级别的调用/实现,则不会。。。。考虑进位先行、进位保存加法器等。
@Array=()不会释放基础数组。即使超出范围也不会这样做。如果你想释放底层数组,你必须使用
undf@array演示<代码>perl-MDevel::Peek-e'my@a;转储(\@a,1)@a=qw(a b c);转储(\@a,1)@a=();转储(\@a,1);未定义@a;转储(\@a,1);'2> &1| grep数组
什么???我原以为GC的全部要点是一旦ref count==0,所涉及的内存就可以回收。@ikegami:我看到了
()
vs
undef
,但是如果超出作用域并没有释放该作用域本地数组使用的内存,这难道不会使perl成为泄漏灾难吗?那不可能是真的。它们也不会泄漏。sub仍然拥有它们,并将在下次调用sub时重用它们。优化了速度。我希望
每一个
都是最慢的。它完成了其他人的所有工作,减去一个别名,再加上一个列表分配,两个标量副本和两个标量清除。使用
对数组的索引进行迭代时大约快45%,对数组引用的索引进行迭代时快20%(我确实访问了
$array->[$I]
,在正文中),使用
每个
同时使用
.Wow,你用简短的句子添加了大量的信息。#2在排队时很有用(例如广度优先搜索):
my@todo=$root;而(@todo){my$node=shift。。。;
undef @Array;
for my $el (@Array) {
# ...
}
for my $i (0 .. $#Array) {
# ...
}
while (my ($i, $el) = each @Array) {
# ...
}
my @array = qw( 1 2 3 );
for (@array) {
        $_ = $_ *2 ;
}
print "@array";
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)