【问题标题】:Why doesn't Perl's each() iterate through the entire hash the second time?为什么 Perl 的 each() 不第二次遍历整个散列?
【发布时间】:2010-11-10 13:20:42
【问题描述】:

我有一个简单的脚本试图学习 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”个元素,具体取决于内部排序。但是为什么我不能在之后循环数组呢?怎么了 ?

谢谢,

【问题讨论】:

    标签: perl hash iteration


    【解决方案1】:

    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

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

    【讨论】:

    • 谢谢。顺便说一句,是否可以将“每个”重置为开头?
    • (perlfaq4 建议在 void 上下文中对散列调用“keys”。这可能会避免不必要的复制。)
    【解决方案2】:

    你可以阅读每个文档的 perldoc

    perldoc -f each
    

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

    【讨论】:

      猜你喜欢
      • 2012-11-18
      • 2012-08-03
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      • 2013-04-21
      • 1970-01-01
      相关资源
      最近更新 更多