2012-10-17 20 views
5
「的foreach」的

我剛開始學習Perl,發現自己通過下面的代碼塊的結果阻礙:行爲在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而言,循環完成了嗎?

回答

8

您可能不應該在迭代過程中修改列表。從perldoc perlsyn

如果LIST任何部分是一個數組,如果你splice循環體中添加或刪除元素,例如foreach會得到非常困惑。所以不要這樣做。

如果循環(print ("$x $y $_\n");)時打印出來$_,你可以看到這是怎麼回事:

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

在這種情況下,Perl是剛剛維持它通過增加數組的索引。由於您從頭開始刪除元素,因此索引將在第四次迭代結束時從修改數組末尾跳下,因此foreach循環終止。

+0

感謝nneonneo。你對發生什麼的解釋正是我需要理解的。 – verbose

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正在interpreted in scalar context,因此while循環將持續到元件的數量在@x中爲零。

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 ([email protected]/2) { 
    my $x = $x[-$_]; 
    my $y = $x[$_-1]; 
    print("$x $y\n"); 
}