当从标准输入读取时,while和foreach有什么区别?

6
可能重复:
在Perl中使用foreach或while迭代文件的区别是什么? 在while循环中,Perl读取一行输入并将其放入变量中,然后运行循环体。然后,它返回查找另一行输入。但是,在foreach循环中,线路输入运算符在列表上下文中使用(因为foreach需要一个列表来迭代)。因此,在循环开始运行之前,它必须读取所有输入。当输入来自400 MB Web服务器日志文件时,这种差异会变得明显!通常最好使用while循环的快捷方式,该方式将尽可能逐行处理输入。来源-《Llama书》 那么我应该每次都使用while吗?什么情况下foreach循环会优于while循环?
3个回答

7
正如你所指出的那样,使用foreach循环遍历文件会在循环开始之前将文件读入内存。
虽然Perl的信条之一是“有多种方法可用于解决一个问题”,但存在某些没有实际好处的方法。foreach可能不是循环遍历文件的最佳选择。如果要逐行遍历文件,则通常使用while()。如果要将整个文件一次性读入内存,请完成这一步骤并结束操作。
有时将整个文件读入内存会带来优势。例如,其中之一就是使文件打开时间最小化。往往情况下,这是为了方便处理不符合按行或按记录模型的数据。foreach() slurps the file,但并没有真正提供关闭文件的良机,因此这种好处就不存在了。而且,如果您的数据必须视为块进行处理,使用foreach循环遍历文件也无法帮助您太多。所以这个原因也没有了。最终,您得到了读取文件的负面效果,却没有读取文件的任何正面效果。
总会有人想出比别人更聪明的理由。但我还没有看到过这种情况。(通常当我说这样的话时,有人会发帖表示反对,所以绝对地认为它没有价值总是很危险的。)换句话说,在您发现使用foreach遍历文件的极少数良好原因之前,不用担心它。当您确实发现这一点时,您会知道是时候了。

6
一般而言,如果你使用的对象在使用过程中会发生变化,就应该使用 while 循环:
while(my $line = <>)
while(my ($k, $v) = each %h)

但如果不是 for 或者 foreach:

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";
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接