5

私はPerlの学習を始めたばかりで、次のコード ブロックの結果に悩まされていることに気付きました。

@x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
foreach (@x) {
    $x = pop (@x) ;
    $y = shift (@x);
    print ("$x $y \n");
}

出力は次のとおりです。

10 1
9 2
8 3
7 4

私は別の行を期待していました: 6 5. なんでそんなセリフないの?を出力する反復の後、7 4配列に残っている要素の数は、既に完了した反復の数と等しくなり、Perl に関する限り、ループが完了したためですか?

4

3 に答える 3

8

おそらく、反復中にリストを変更するべきではありません。差出人perldoc perlsyn

のいずれかの部分がLIST配列であるforeach場合、たとえば。を使用してループ本体内の要素を追加または削除すると、非常に混乱しますsplice。だからそうしないでください。

$_ループ中に印刷すると( print ("$x $y $_\n");)、何が起こっているかを確認できます。

10 1 1
9 2 3
8 3 5
7 4 7

この場合、Perlは配列を介してインクリメントするインデックスを維持しているだけです。要素を最初から削除するため、4回目の反復の終わりにインデックスが変更された配列の最後から外れ、foreachループが終了します。

于 2012-10-17T05:16:20.000 に答える
7

これは、反復している配列を変更したときに何が起こるかを示す良い例です。

試す:

use strict: #Always!
use warnings; #Always!

my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
my $n=$#x;
foreach my $i(0..$n) {
    my $x = pop (@x) ;
    my $y = shift (@x);
    print "$x $y\n" if defined $x and defined $y;
}

または、さらに良い:

use strict;
use warnings;

my @x=1..10; #same thing, just written more idiomatically

while(@x)
{
  my $x=pop @x; #no parentheses needed
  my $y=shift @x;
  print "$x $y\n";
}

上記のwhileループでは、配列@xスカラーコンテキストで解釈されているため、whileループはの要素数@xがゼロになるまで続きます。

于 2012-10-17T05:17:35.330 に答える
3

foreach ループを使用して反復している配列を変更することはできません。

とにかく、配列要素を反復処理したくありません。foreach (@x)は明らかに間違っています。これは 10 回ループしますが、5 回だけループしたいとします。

ループするときに配列から要素を削除するため、配列が空になるまでループするだけです。ループを通過するたびに条件をチェックするには、while ループを使用します。

my @x = 1..10;
while (@x) {
    my $x = pop(@x) ;
    my $y = shift(@x);
    print("$x $y\n");
}

foreach ループを使用する場合は、次のようになります。

my @x = 1..10;
for (1..@x/2) {
    my $x = $x[-$_];
    my $y = $x[$_-1];
    print("$x $y\n");
}
于 2012-10-17T05:50:36.957 に答える