perl 101 - 迭代哈希导致永不结束循环

时间:2013-08-21 19:49:17

标签: perl

不知道为什么这个脚本无限运行。 它看起来很好。


while (my ($k, $v) = each (%ENV)){
 my @k = keys (%ENV);
 if($k eq $k[0]){
   print "ok";
  }
}

3 个答案:

答案 0 :(得分:12)

keys(以及values)函数重置each函数使用的迭代器。由于键没有改变,你可以在循环之外检索它们。

答案 1 :(得分:9)

在循环内调用keys会重置each使用的迭代器。不要那样做。这应该有效:

my @k = keys (%ENV);
while (my ($k, $v) = each (%ENV)){
 if($k eq $k[0]){
   print "ok";
  }
}

答案 2 :(得分:0)

主要问题已被其他人回答,但我想提醒我们不要使用while-each-loop迭代哈希。 如果你想处理整个哈希,我建议不要使用这个构造:

while (my ($k, $v) = each %HASH) {
}

为什么呢?此循环将从哈希迭代器留在%HASH中的当前位置开始。如果散列迭代器不在开头,那么这将只处理散列的一部分而不是整个散列。 例如:

use strict;
use warnings;

# demonstrate hash iterator behaviour with each():
sub somefunc {
    my ($test_ref, $string) = @_;
    while (my ($k, $v) = each %$test_ref) {
            if ($k eq $string){
                    print "$string found\n";
                    return;
            }
    }
    print "$string not found\n";
}

my %test = (
    foo => 'a',
    bar => 'b'
);

somefunc(\%test, 'foo');
somefunc(\%test, 'foo');

这将打印:

foo found
foo not found

我曾经使用while-each-loop来检查深层嵌套数据结构中的某些值。然后我使用return或last退出循环。这使得哈希迭代器悬挂在我正在检查的最后位置。很久以后,在不同的模块中,在不同的函数中,我继续使用while-each-loop再次处理哈希,假设它将处理整个哈希。然而,它继续在散列迭代器的最后位置处理,仅处理散列的其余部分。这是一个很难找到的错误。

如果要使用each()来处理整个哈希值,则应始终使用键%HASH作为前缀。例如:

keys %HASH; # keys will reset the hash iterator
while (my ($k, $v) = each %HASH) { # will really process the ENTIRE hash
}

Mark Reeds上面的例子也总是有效,因为他在执行while-each-loop之前调用键%ENV。通过使用keys(),哈希迭代器被重置,因此while-each-loop将处理整个哈希值。