Perl,检查对是否存在散列哈希值

时间:2010-12-02 15:23:56

标签: perl hash

在Perl中,我有一个使用类似于以下

的循环创建的哈希哈希
    my %HoH
    for my $i (1..10) {
      $HoH{$a}{$b} = $i; 
    }

$ a和$ b是在HoH填写时确实具有某些值的变量。在创建HoH之后,如何检查HoH中是否存在特定的对($ c,$ d)?以下不起作用

if (defined $HoH{$c}{$d}) {...}

因为如果已经在HoH中不存在$ c,它将被创建为没有值的键。

5 个答案:

答案 0 :(得分:4)

书写

if (defined $HoH{$c}{$d}) {...}

会“工作”,因为它会告诉你$HoH{$c}{$d}是否有定义的值。问题是,如果$HoH{$c}尚不存在,则会创建它(具有适当的值),以便可以测试$HoH{$c}{$d}。这个过程称为“自动化”。设置值时很方便,例如

my %hoh;
$hoh{a}{b} = 1; # Don't need to set '$hoh{a} = {}' first

但在检索可能不存在的值时不方便。我希望Perl足够聪明,只能对用作左值和短路的表达式执行自动修复,以便为rvalues返回undef,但是,唉,这不是那么神奇。 autovivification pragma(在CPAN上可用)添加了执行此操作的功能。

为避免自动更新,您需要先测试中间值:

if (exists $HoH{$c} && defined $HoH{$c}{$d}) {
     ...
}

答案 1 :(得分:3)

use Data::Dumper;

my %HoH;

$HoH{A}{B} = 1;

if(exists $HoH{C} && exists $HoH{C}{D}) {
   print "exists\n";
}

print Dumper(\%HoH);

if(exists $HoH{C}{D}) {
   print "exists\n";
}

print Dumper(\%HoH);

输出:

$VAR1 = {
          'A' => {
                   'B' => 1
                 }
        };
$VAR1 = {
          'A' => {
                   'B' => 1
                 },
          'C' => {}
        };

自动生成导致创建密钥。我的第二个示例中的“exists”显示了这一点,因此第一个示例单独检查两个键。

答案 2 :(得分:2)

有几种方法:

if ( $HoH{$c} && defined $HoH{$c}{$d} ) {...}

if ( defined ${ $HoH{$c} || {} }{$d} ) {...}

no autovivification;
if (defined $HoH{$c}{$d}) {...}

use Data::Diver;
if ( defined Data::Diver::Dive( \%HoH, $c, $d ) ) {...}

答案 3 :(得分:0)

您必须使用exists功能

  

存在EXPR

     

给定一个指定一个表达式   哈希的元素,如果是,则返回true   哈希中的指定元素曾经存在过   已经初始化,即使是   相应的值未定义。

     

请注意,EXPR可以是任意的   只要决赛复杂   operation是哈希或数组键   查找或子程序名称:

     
      
  1. if(exists $ ref-> {A} - > {B} - > {$ key}){}
  2.   
  3. if(exists $ hash {A} {B} {$ key}){}
  4.   

答案 4 :(得分:0)

我的看法:

use List::Util   qw<first>;
use Params::Util qw<_HASH>;

sub exists_deep (\[%$]@) {
    my $ref = shift;
    return unless my $h = _HASH( $ref ) // _HASH( $$ref )
              and defined( my $last_key = pop )
              ;
    # Note that this *must* be a hash ref, for anything else to make sense.
    return if first { !( $h = _HASH( $h->{ $_ } )) } @_;
    return exists $h->{ $last_key };
}

您也可以递归地执行此操作。您还可以创建一个下降结构,允许中间甚至是终端arrayref,只需要一些额外的编码。