如何测试散列中是否存在值?

时间:2011-01-14 23:42:40

标签: perl

让我说我有这个

#!/usr/bin/perl

%x = ('a' => 1, 'b' => 2, 'c' => 3);

我想知道值2是%x中的哈希值。

这是怎么做到的?

6 个答案:

答案 0 :(得分:17)

从根本上说,哈希是为解决相反问题而优化的数据结构,知道 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]完全返回您作为布尔值请求的信息,并表现出短路行为 自5.10以来,Smart matching在Perl中可用。

重复操作,静态哈希

构造一个将值映射到键的哈希,并将其用作自然哈希来测试键的存在。

my %r = reverse %x;
if ( exists $r{2} ) { ... }

重复操作,动态散列

使用上面的反向查找。你需要保持它是最新的,这是作为练习给读者/编辑。 (提示:价值冲突很棘手)

答案 1 :(得分:10)

使用智能匹配(Perl版本5.10或更高版本)的更短答案:

print 2 ~~ [values %x];

答案 2 :(得分:8)

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

答案 3 :(得分:7)

到目前为止,每个人的答案都不是以绩效为导向的。虽然智能匹配(~~)解决方案短路(例如,在找到某些内容时停止搜索),但grep解决方案不会。

因此,这是一个解决方案,它可能在5.10之前具有更好的性能,没有智能匹配运算符:

use List::MoreUtils qw(any);
if (any { $_ == 2 } values %x) {
    print "Found!\n";
}

请注意,这只是在这种情况下搜索列表(values %x)的一个具体示例,因此,如果您关心性能,则在列表中搜索的标准性能分析将应用为{{ 3}}

答案 4 :(得分:5)

grepvalues

my %x = ('a' => 1, 'b' => 2, 'c' => 3); 

if (grep { $_ == 2 } values %x ) {
    print "2 is in hash\n";
}
else {
    print "2 is not in hash\n";
}

另请参阅:perldoc -q hash

答案 5 :(得分:3)

结果是$ count:

my $count = grep { $_ == 2 } values %x;

这不仅会告诉您它是否是散列中的值,而是它作为值出现的次数。或者你也可以这样做:

my $count = grep {/2/} values %x;