当从STDIN读书时,与foreach相比

时间:2011-07-15 04:12:34

标签: perl loops foreach while-loop

  

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

  

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

我每次都应该使用while吗? foreach循环可能会在什么情况下占主导地位?

3 个答案:

答案 0 :(得分:7)

正如您所指出的,在循环开始之前,使用foreach遍历文件会将文件丢入内存。

虽然Perl的一个信条确实是“有多种方式可以做到”,但是存在一些方法可以做一些其他方式没有实际好处的事情。 foreach可能是循环文件的不良替代方案。如果您要逐行迭代文件,通常使用while()。如果您要将整个文件一次性打入内存,只需一步即可完成,然后完成。

有时可能会有利于整个文件的诋毁。例如,其中之一是最小化必须打开文件的时间。通常情况下,它是为了方便处理不一致的数据或按记录模型记录的数据。 foreach()会篡改文件,但实际上并没有提供立即关闭它的好机会,因此好处就消失了。如果您的数据必须被视为一个块,那么使用foreach循环遍历该文件对您没有多大帮助。所以这个理由也消失了。最后,你得到了诋毁文件的负面消息,没有任何积极的诽谤文件。

总会有人提出一个其他人没有考虑的聪明理由。但我还没有看到它。 (通常当我说某人发布“it”之类的东西时,所以建议它绝对没有任何优点总是危险的。)让我们这样说:直到你发现使用foreach迭代一个极少的好理由之一文件,不要担心。当你确实做出这个发现时,你会知道现在是时候了。

答案 1 :(得分:6)

一般的经验法则是,如果您正在使用的东西在使用时发生变化,请使用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将是迭代它的更自然的选择。

答案 2 :(得分: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";
}