我的问题很简单。我必须从散列中打印一些键值对。我尝试了两种不同的方法:
方法A
#Fill hash from file ($fh has been defined previously)
while(my $line = <$fh>) {
$counter{$line}++;
}
foreach (my($k, $v) = each %counter){
my ($p1, $p2) = split(/$;/o, $k);
chomp $p2;
if($v > 0){
printf "%s_down_%s %s %dn", $prefix, $p1, $p2, $v;
printf "%s_up_%s %s %dn", $prefix, $p2, $p1, $v;
}
}
方法B
#Fill hash from file ($fh has been defined previously)
while(my $line = <$fh>) {
$counter{$line}++;
}
foreach $k (keys %counter) {
my ($p1, $p2) = split(/$;/o, $k);
my $v = $counter{$p1,$p2};
chomp $p2;
if($v > 0){
printf "%s_down_%s %s %dn", $prefix, $p1, $p2, $v;
printf "%s_up_%s %s %dn", $prefix, $p2, $p1, $v;
}
}
阅读代码时,我会说两个方法都得到了相同的结果,但在执行后,方法B得到了正确的结果,而法A只打印了两个元素(4行)。
在多次运行方法A之后,我可以看到每次执行时打印的元素都会发生变化。
有人知道这里发生了什么吗?
将foreach
与each
一起使用是错误的
perl -wE'%h=(a=>1,b=>2,c=>3); for (($k, $v) = each %h) { say "$k => $v" }'
打印
c=>3c=>3
用while
代替foreach
,我们得到了正确的行为。
这是错误的,可以从每个(我的重点)中看出
在列表上下文中对哈希调用时,返回一个2元素列表,该列表由哈希的下一个元素的键和值组成。
因此each
迭代,并且由于foreach
首先生成整个列表(要迭代),因此each
以(明显)定义不清的方式在内部迭代;这可能表现出未定义的行为。我们最终得到了一个不正确的键值对列表,供foreach
迭代(使用each
内部形成)。
仔细阅读each
页面,了解使用keys
、values
和each
的更多细节。
一个更有说服力的示例
perl -wE'@h{("a".."f")} = (1..6); for (($k, $v) = each %h) { say "$k => $v" }'
在我的系统上打印
e=>5e=>5
使用while
正确运行时,首先返回e => 5
对。所以我们得到了那双,两次。
(仍在试图找出原因两次…)