6

我有一个简单的脚本试图了解 Perl 中的哈希。

#!/usr/bin/perl

my %set = (
    -a => 'aaa',
    -b => 'bbb',
    -c => 'ccc',
    -d => 'ddd',
    -e => 'eee',
    -f => 'fff',
    -g => 'ggg'
);

print "Iterate up to ggg...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
    last if ($val eq 'ggg');
}
print "\n";

print "Iterate All...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
}
print "\n";

我对输出感到惊讶:-

Iterate upto ggg...
-a -> aaa
-c -> ccc
-g -> ggg

Iterate All...
-f -> fff
-e -> eee
-d -> ddd
-b -> bbb

我知道键是散列的,因此第一个输出可以是“n”个元素,具体取决于内部排序。但是为什么我不能在之后循环数组呢?怎么了 ?

谢谢,

4

2 回答 2

18

each使用与哈希关联的指针来跟踪迭代。它不知道第一个 while 与第二个 while 循环不同,并且在它们之间保持相同的指针。

大多数人each出于这个(和其他)原因避免,而是选择keys

for my $key (keys %hash){
    say "$key => $hash{$key}";
}

这也使您可以控制迭代顺序:

for my $key (sort keys %hash){
    say "$key => $hash{$key}";
}

无论如何,如果您要提前结束循环,请避免each.

顺便说一句,函数式编程的倡导者应该借此机会指出隐藏状态的缺点。看起来像无状态操作(“循环遍历表中的每一对”)实际上是有状态的。

于 2009-07-14T06:09:38.287 回答
10

您可以阅读每个文件的 perldoc

perldoc -f each

当哈希被完全读取时,在列表上下文中返回一个空数组(分配时产生一个假(0)值),在标量上下文中返回“undef”。之后对“每个”的下一次调用将再次开始迭代。每个散列都有一个迭代器,由程序中的所有“each”、“keys”和“values”函数调用共享;它可以通过读取散列中的所有元素,或通过评估“keys HASH”或“values HASH”来重置。

因此,您可以在代码中使用键 %set 再次迭代(由于您的“最后”语句)

print "Iterate upto ggg...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
    last if ($val eq 'ggg');
}
print "\n";
keys %set;
print "Iterate All...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
}
print "\n";
于 2009-07-14T06:15:04.267 回答