我刚刚开始学习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而言,循环完成了吗?
答案 0 :(得分:8)
您可能不应在迭代期间修改列表。来自perldoc perlsyn
:
如果
LIST
的任何部分是数组,如果您在循环体中添加或删除元素,foreach
将会非常混乱,例如使用splice
。所以不要这样做。
如果您在循环($_
)期间打印print ("$x $y $_\n");
,则可以看到正在发生的事情:
10 1 1
9 2 3
8 3 5
7 4 7
在这种情况下,Perl只是维护一个索引,它通过数组递增。由于您从头开始删除元素,因此索引在第四次迭代结束时从修改后的数组的末尾开始,因此foreach
循环终止。
答案 1 :(得分: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
中的元素数为零。< / p>
答案 2 :(得分: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");
}