【问题标题】:while vs foreach when reading from STDIN [duplicate]从STDIN读取时的while vs foreach [重复]
【发布时间】:2011-10-05 20:48:08
【问题描述】:

可能重复:
What's the difference between iterating over a file with foreach or while in Perl?

在 while 循环中,Perl 读取一行输入,将其放入一个 变量,并运行循环体。然后,它回去寻找 另一行输入。但在 foreach 循环中,行输入 运算符正在列表上下文中使用(因为 foreach 需要一个列表 迭代)。所以它必须在 循环可以开始运行。当 输入来自您的 400 MB Web 服务器日志文件!一般是这样 最好使用 while 循环的快捷方式之类的代码,它将处理 尽可能一次输入一行。 来源-The Llama book

所以我应该每次都使用while 吗?在什么情况下foreach 循环将支配while?

【问题讨论】:

    标签: perl loops foreach while-loop


    【解决方案1】:

    正如您所指出的,使用 foreach 迭代文件会在循环开始之前将文件放入内存中。

    虽然 Perl 的信条之一确实是“有不止一种方法可以做到”,但也有一些方法可以做一些与其他方法相比并没有真正好处的方法。 foreach 可能是循环文件的糟糕选择。如果要逐行遍历文件,通常使用while()。如果您打算一次将整个文件放入内存中,您只需一步完成即可。

    啜饮整个文件有时会有好处。例如,其中之一是最小化必须打开文件的时间。通常,这是为了方便处理不适合逐行或逐记录模型的数据。 foreach() slurps 文件,但并没有真正提供立即关闭它的好机会,因此这种好处消失了。如果您的数据必须被视为一个块,那么使用 foreach 循环文件对您没有多大帮助。所以这个理由也没有了。最后,你会得到 slurping 文件的负面影响,而 slurping 文件没有任何积极意义。

    总会有人想出一个别人没有考虑过的聪明理由。但我还没有看到它。 (通常当我说有人发布“它”时,因此暗示它绝对没有价值总是很危险的。)让我们这样说:直到你发现使用 foreach 迭代的极少数充分理由之一文件,不用担心。当然,当您确实发现时,您就会知道是时候了。

    【讨论】:

      【解决方案2】:

      一般的经验法则是使用while,如果您正在使用的东西在您使用它时发生变化:

      while(my $line = <>)
      while(my ($k, $v) = each %h)
      

      forforeach 否则:

      foreach my $line (@lines)
      for my $k (keys %h)
      for(my $i = 0; $i < $pancakes; ++$i)
      

      在文件的情况下,使用while 是有意义的,因为您(可能)不想将整个内容放入内存中(当然,当您确实想要时除外)。但是,如果您的数据已经在内存中,那么 for/foreach 将是一个更自然的选择来迭代它。

      【讨论】:

        【解决方案3】:

        当数据已经在内存中时,您可以使用foreach 迭代数组的每个元素或哈希的每个键。当数据尚未在内存中时使用while(您甚至可能不需要一次将所有数据都保存在内存中)。

        my %hash;
        while (<>)
        {
            chomp;
            my($key, $value) = split /,/;
            $hash{$key} = $value;
        }
        
        foreach my $key (sort keys %hash)
        {
             print "$key => $hash{$key}\n";
        }
        

        【讨论】:

          猜你喜欢
          • 2017-08-16
          • 1970-01-01
          • 2023-04-01
          • 2016-09-07
          • 1970-01-01
          • 1970-01-01
          • 2012-08-11
          • 1970-01-01
          • 2018-12-06
          相关资源
          最近更新 更多