【问题标题】:perl 101 - iterating hash causes never ending loopingperl 101 - 迭代哈希导致永无止境的循环
【发布时间】:2014-01-03 20:16:31
【问题描述】:

不知道为什么这个脚本会无限运行。 我觉得很好。


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

【问题讨论】:

  • 在我看来,整个脚本可以被压缩成仅仅一个print "ok",还是我遗漏了什么?
  • 另见this。如果您真的想这样做,请使用Hash::SafeKeys

标签: perl


【解决方案1】:

keys(以及values)函数重置each 函数使用的迭代器。由于密钥不会改变,您可以在循环之外检索它们。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      其他人已经回答了主要问题,但是我想提醒大家不要使用 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将处理整个哈希。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-04
        • 2023-03-22
        • 1970-01-01
        • 1970-01-01
        • 2014-11-14
        • 2023-04-07
        • 2014-10-27
        相关资源
        最近更新 更多