【问题标题】:while vs foreach when reading from STDIN [duplicate]从STDIN读取时的while vs foreach [重复]
【发布时间】:2011-10-05 20:48:08
【问题描述】:
【问题讨论】:
标签:
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)
但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";
}