为什么Perl的each()第二次不遍历整个哈希?

时间:2009-07-14 06:05:33

标签: perl hash iteration

我有一个简单的脚本试图了解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'个元素,具体取决于内部排序。但为什么我之后无法循环播放数组呢?怎么了 ?

谢谢,

2 个答案:

答案 0 :(得分: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

BTW,函数式编程倡导者应该借此机会指出隐藏状态的缺点。看似无状态的操作(“在表中循环每对”)实际上是非常有状态的。

答案 1 :(得分:10)

你可以阅读每个

上的perldoc
perldoc -f each

当完全读取哈希值时,在列表上下文中返回一个空数组(当分配时产生一个false(0)                值)和标量上下文中的“undef”。之后对“each”的下一次调用将再次开始迭代。有一个罪 -                每个哈希的gle迭代器,由程序中的所有“each”,“keys”和“values”函数调用共享;它可以重置                从散列中读取所有元素,或者通过评估“键HASH”或“值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";