【发布时间】:2020-10-26 20:29:06
【问题描述】:
假设我有这个
#!/usr/bin/perl
%x = ('a' => 1, 'b' => 2, 'c' => 3);
我想知道值 2 是否是 %x 中的哈希值。
这是怎么做到的?
【问题讨论】:
标签: perl
假设我有这个
#!/usr/bin/perl
%x = ('a' => 1, 'b' => 2, 'c' => 3);
我想知道值 2 是否是 %x 中的哈希值。
这是怎么做到的?
【问题讨论】:
标签: perl
从根本上说,散列是一种为解决相反问题而优化的数据结构,知道 key 2 是否存在。但是在不知道的情况下很难判断,所以我们假设不会改变。
此处介绍的可能性取决于:
grep $_==2, values %x(也拼写为grep {$_==1} values %x)将返回一个列表,其中包含与散列中存在的一样多的 2,或者在标量上下文中,匹配的数量。在条件中作为布尔值进行评估,它会产生您想要的结果。grep 适用于我记忆中最古老的 Perl 版本。use List::Util qw(first); first {$_==2} values %x 仅返回第一个匹配项,undef 如果没有。这使它更快,因为一旦成功它就会短路(停止检查元素)。这对 2 来说不是问题,但请注意返回的元素不一定评估为布尔值 true。在这些情况下使用 defined。List::Util 自 5.8 起成为 Perl 核心的一部分。use List::MoreUtils qw(any); any {$_==2} values %x 以布尔值的形式准确返回您请求的信息,并表现出短路行为。List::MoreUtils 可从 CPAN 获得。2 ~~ [values %x] 以布尔值的形式准确返回您请求的信息,并表现出短路行为。构造一个将值映射到键的散列,并将该散列用作自然散列来测试键的存在。
my %r = reverse %x;
if ( exists $r{2} ) { ... }
如上所述使用反向查找。您需要使其保持最新状态,这留给读者/编辑作为练习。 (提示:值冲突很棘手)
【讨论】:
使用智能匹配缩短答案(Perl 版本 5.10 或更高版本):
print 2 ~~ [values %x];
【讨论】:
my %reverse = reverse %x;
if( defined( $reverse{2} ) ) {
print "2 is a value in the hash!\n";
}
如果要找出值为 2 的键:
foreach my $key ( keys %x ) {
print "2 is the value for $key\n" if $x{$key} == 2;
}
【讨论】:
到目前为止,每个人的回答都不是以性能为导向的。虽然智能匹配 (~~) 解决方案会短路(例如,在找到某些东西时停止搜索),但 grep 解决方案不会。
因此,这是一个在 5.10 之前可能对没有智能匹配运算符的 Perl 性能更好的解决方案:
use List::MoreUtils qw(any);
if (any { $_ == 2 } values %x) {
print "Found!\n";
}
请注意,这只是在这种情况下在列表中搜索 (values %x) 的一个具体示例,因此,如果您关心性能,则在列表中搜索的标准性能分析适用于 discussed in detail in this answer
【讨论】:
$count 将是结果:
my $count = grep { $_ == 2 } values %x;
这不仅会显示它是否是散列中的值,还会显示它作为值出现的次数。或者,您也可以这样做:
my $count = grep {/2/} values %x;
【讨论】: