106

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 ;
4

6 に答える 6

83
  • 速度に関しては、1 位と 4 位ですが、ほとんどの場合、それほどではありません。

    確認のためにベンチマークを作成することもできますが、反復作業が Perl ではなく C で行われ、配列要素の不必要なコピーが発生しないため、#1 と #4 がわずかに高速であることがわかると思います。($_は#1 の要素にエイリアスされていますが、#2 と #3 は実際には配列からスカラーをコピーしています。)

    #5も似てるかも。

  • メモリ使用量に関しては、#5 を除いてすべて同じです。

    for (@a)配列の平坦化を避けるために特殊なケースになっています。ループは、配列のインデックスを反復処理します。

  • 読みやすさに関しては、#1。

  • 柔軟性に関しては、#1/#4 と #5 です。

    #2 は false の要素をサポートしていません。#2と#3は破壊的です。

于 2012-05-07T20:00:05.837 に答える
31

の要素のみを気にする場合は@Array、次を使用します。

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

また

インデックスが重要な場合は、次を使用します。

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

または、perl5.12.1 以降では、以下を使用できます。

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

ループの本体で要素とそのインデックスの両方が必要な場合は、私は期待するだろう使用してeach 最速になりますが、その後5.12.1 より前のperls との互換性を放棄することになります。

特定の状況下では、これら以外のパターンが適切な場合があります。

于 2012-05-07T23:19:56.110 に答える
3

IMO、実装#1は典型的であり、Perlにとって短くて慣用的であるため、それだけで他の実装よりも優れています。3 つの選択肢のベンチマークは、少なくとも速度についての洞察を提供する可能性があります。

于 2012-05-07T19:03:48.650 に答える
2

1 は 2 および 3 とは大きく異なります。これは、配列をそのままにしておくのに対し、他の 2 つは空のままにするためです。

#3はかなり風変わりで、おそらく効率が悪いと思いますので、忘れてください。

これにより、#1と#2が残りますが、それらは同じことをしないため、一方が他方よりも「優れている」ことはありません. 配列が大きく、それを保持する必要がない場合、通常はスコープで処理されます (ただし、を参照 してください)。そのため、一般的には、#1 が依然として最も明確で単純な方法です。各要素をオフにシフトしても、速度は上がりません。配列を参照から解放する必要がある場合でも、次のようにします。

undef @Array;

それが終わったら。

  • : 配列のスコープを含むサブルーチンは、実際には配列を保持し、次回はスペースを再利用します。一般に、それで問題ないはずです(コメントを参照)。
于 2012-05-07T19:01:03.847 に答える
1

要素または配列を 1 行で出力します。

print $_ for (@array);

注: $_ は、ループ内の @array の要素を内部的に参照していることに注意してください。$_ で行われた変更は @array に反映されます。 元。

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

出力: 2 4 6

于 2017-03-30T09:09:59.870 に答える