【问题标题】:How to test if a value exist in a hash?如何测试一个值是否存在于哈希中?
【发布时间】:2020-10-26 20:29:06
【问题描述】:

假设我有这个

#!/usr/bin/perl

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

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

这是怎么做到的?

【问题讨论】:

    标签: perl


    【解决方案1】:

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

    重复操作,静态哈希

    构造一个将值映射到键的散列,并将该散列用作自然散列来测试键的存在。

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

    重复操作,动态哈希

    如上所述使用反向查找。您需要使其保持最新状态,这留给读者/编辑作为练习。 (提示:值冲突很棘手)

    【讨论】:

      【解决方案2】:

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

      print 2 ~~ [values %x];
      

      【讨论】:

      • 请在您的回答中注意这只是 5.10+
      【解决方案3】:
      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;
      }
      

      【讨论】:

      • 如果您需要进行大量反向查找,这是一个不错的计划。但是对于一个反向查找来说,它是矫枉过正的。
      【解决方案4】:

      到目前为止,每个人的回答都不是以性能为导向的。虽然智能匹配 (~~) 解决方案会短路(例如,在找到某些东西时停止搜索),但 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

      【讨论】:

        【解决方案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

        【讨论】:

          【解决方案6】:

          $count 将是结果:

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

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

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

          【讨论】:

            猜你喜欢
            • 2012-08-10
            • 1970-01-01
            • 2016-06-30
            • 1970-01-01
            • 1970-01-01
            • 2011-11-26
            • 1970-01-01
            • 2012-02-19
            • 1970-01-01
            相关资源
            最近更新 更多