为什么减少{}没有按预期返回最大值?

时间:2015-01-22 17:42:35

标签: perl hash max reduce

我需要在Perl哈希中找到所有值的最大值。我不需要键,只需要最高值,这样我就可以增加它并返回一个比以前更高的新值。世界上最简单的事情。我从这个答案中获得灵感:https://stackoverflow.com/a/2891180/2740187,并实现了这段代码:

use List::Util qw( reduce min max );
my %gid = ("abc" => 1, "def" => 1);
my $gid_ref = \%gid;
my $max_gid = reduce { $a > $b ? $a : $b } values %$gid_ref || 0;
print "$max_gid\n"; 

如您所见,哈希只包含两个1作为值。那为什么打印“2”?至少它在我的机器上。

我想我可以写

my $max2 = max(values %$gid_ref) || 0;

无论如何要获得最大值,但我真的想了解这里发生的事情。

2 个答案:

答案 0 :(得分:8)

这一行

my $max_gid = reduce { $a > $b ? $a : $b } values %$gid_ref || 0;

被解析为

my $max_gid = reduce { $a > $b ? $a : $b } (values %$gid_ref || 0);

(values %$gid_ref || 0)

在标量上下文中使用values,它计算哈希值(2)中的元素数。由于2 || 0仍为2,因此您可以对标量执行缩减并获取值。

另一方面

my $max_gid = (reduce { $a > $b ? $a : $b } values %$gid_ref) || 0;

确实按预期获得序列的最大值。

|| 0的目的是什么?文档建议

  

如果您的算法要求reduce生成一个标识值,那么请确保始终将该标识值作为第一个参数传递,以防止返回undef。

所以你可能想要

my $max_gid = reduce { $a > $b ? $a : $b } 0, values %$gid_ref;

答案 1 :(得分:2)

您还可以使用较低优先级or运算符而不是||运算符,它不会在values()上强加标量上下文

my $max_gid = (reduce { $a > $b ? $a : $b } values %$gid_ref or 0);

(这里必须使用括号,如果省略则会发出警告)