有没有一种简单的方法来验证散列元素的散列存在和被定义?

问题描述:

我需要验证散列元素的Perl散列,如$Table{$key1}{$key2}存在并被定义。这是我做的。 (我不知道$key1存在的话)有没有一种简单的方法来验证散列元素的散列存在和被定义?

if 
((defined $Table{$key1}) && 
(exists $Table{$key1}) && 
(defined $Table{$key1}{$key2}) && 
(exists $Table{$key1}{$key2})) 
{ 
    #do whatever 
} 

是否有更简单和更清洁的方式做到这一点?

+0

请编辑您的问题使用代码块代码。 – justkt 2010-04-27 17:36:53

你不需要检查每个等级的等级:你可以为你关心的价值。 exists不检查定义,只有当散列中的槽存在(它可能存在一个未定义的值),所以如果你关心定义的值,你需要调用defined而不是存在。如果没有定义的值,它计算在布尔上下文中为假,所以我们可以键入少一点,减少您的例子:

if ($Table{$key1}{$key2}) 
{ 
    # do whatever 
} 

但是,如果该键的值定义,但“假” (数值计算结果为零,或为空字符串),这可能会导致假阴性,所以我们应该明确地检查definedness如果这是一个可能性:

if (defined $Table{$key1}{$key2}) 
{ 
    # do whatever 
} 

如果你不想autovivify $Table{$key1},你可以检查其存在第一,这给我们带来了“最好”的方式对于一般情况

if (exists $Table{$key1} and defined $Table{$key1}{$key2}) 
{ 
    # do whatever 
} 

如果你要这个做了很多关于各个领域中的哈希,你可能要增加一些面向对象式的存取方法,其愿意为你做这项工作:

sub has_field 
{ 
    my ($this, $fieldName) = @_; 
    return exists $this->{data} && defined $this->{data}{$fieldName}); 
} 

我敢肯定你已经阅读过它,但它不能伤害再次阅读相关文章:

鉴于指定的哈希元素或数组元素,exists返回true,如果在散列或数组中指定的元件曾经被初始化的表达,即使相应的值是未定义。如果该元素不存在,则该元素不会自动生效。
...
散列或数组元素可以是真实的,只有当它的定义,如果它存在定义,但反过来不一定成立。

+2

这将始终autovivifiy'$表{$键1}'如果它不存在 – 2010-04-27 17:47:57

+0

@Eric:看到最新的编辑:) – Ether 2010-04-27 17:49:39

+1

我会做出错误的代码通过将各种意见围绕它说:“唐脱颖而出不要这样做!!!!!!!“ – 2010-04-27 18:41:18

以下是短,从autovivifcation将保护:不需要

if (exists $table{$key1} and defined $table{$key1}{$key2}) {...} 

在你的代码的其他检查。

检查存在,然后再定义的烦躁。 (A值可以不被限定,但没有现有不能定义存在。)应该与exists测试中间水平,以防止意外的自动激活。在过去的水平,你只需要调用defined。当没有太多层可以很容易地直接代码:

if (exists $hash{a} && defined $hash{a}{b}) {...} 

如果有许多层,这得到尴尬:

if (exists $hash{a} && exists $hash{a}{b} && exists $hash{a}{b}{c} ...) {...} 

在这种情况下,你可以写一个版本的defined那并不“T autovivify中间值:

sub safe_defined { 
    my $h = shift; 

    foreach my $k (@_) { 
     if (ref $h eq ref {}) { 
      return unless exists $h->{$k}; 
      $h = $h->{$k}; 
     } 
     else { 
      return; 
     } 
    } 

    return defined $h; 
} 

你使用这种方式:

if (safe_defined(\%hash, qw(a b c))) { 
    say $hash{a}{b}{c}; 
} 

注:该版本功能是有限的。

  • 它只能处理嵌套的哈希值。 Perl中,您可以构造任意的数据 结构,像标引用数组的哈希...
  • 它不支持有福引用(即对象)。

一个真正的通用版本就留给读者自己练习。 ;)

你可以检查出Data::Diver。它没有autovivifying潜入数据结构。语法是:

if (defined Dive(\%Table, $key1, $key2)) { ... } 

甚至:

if (defined(my $value = Dive(\%Table, $key1, $key2))) { 
    ...do something with $value... 
} 

太好了!谢谢大家的回复。

由于autovivifying对我来说是一个问题,目前我使用的是 “尴尬” 的方式,即 如果(存在$表{$键1} & &定义$表{$键1} {$键2}){

什么就做什么

}

它为我,但是作为你们说的,我有3-4级深度嵌套散列,代码凌乱位。

我会检查出数据:潜水员。那个看起来更好。

再次感谢,