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

San*_*ing 10 perl

假设我有这个

#!/usr/bin/perl

%x = ('a' => 1, 'b' => 2, 'c' => 3);
Run Code Online (Sandbox Code Playgroud)

我想知道值2是否是哈希值%x.

怎么做的?

JB.*_*JB. 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起,Perl中提供了
    智能匹配.

重复操作,静态哈希

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

my %r = reverse %x;
if ( exists $r{2} ) { ... }
Run Code Online (Sandbox Code Playgroud)

重复操作,动态哈希

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


mob*_*mob 10

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

print 2 ~~ [values %x];
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这仅适用于 5.10+ (2认同)

Can*_*ice 9

my %reverse = reverse %x;
if( defined( $reverse{2} ) ) {
  print "2 is a value in the hash!\n";
}
Run Code Online (Sandbox Code Playgroud)

如果要查找值为2的键:

foreach my $key ( keys %x ) {
  print "2 is the value for $key\n" if $x{$key} == 2;
}
Run Code Online (Sandbox Code Playgroud)


DVK*_*DVK 7

到目前为止,每个人的答案都不是以绩效为导向的.虽然smart-match(~~)解决方案短路(例如,当找到某些东西时停止搜索),但grep那些没有.

因此,对于没有智能匹配运算符的5.10之前的Perl可能具有更好性能的解决方案:

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

请注意,这只是values %x在这种情况下搜索列表()的一个具体示例,因此,如果您关心性能,则在列表中搜索的标准性能分析适用于此答案中详细讨论


too*_*lic 5

grep

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";
}
Run Code Online (Sandbox Code Playgroud)

也可以看看: perldoc -q hash