有没有一种简单的方法来验证哈希元素的哈希是否存在并被定义?

时间:2010-04-27 17:34:54

标签: perl hash nested defined

我需要验证存在并定义的散列元素(如$Table{$key1}{$key2})的Perl散列。这就是我的工作。 (我不知道$key1甚至存在)

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

有更简单,更清洁的方法吗?

5 个答案:

答案 0 :(得分:8)

你不需要检查层次结构的每个级别:你可以只追求你关心的价值。 exists不检查定义,只有散列中的槽存在(它可能存在未定义的值),所以如果你关心定义了值,你需要调用defined而不是存在。如果没有定义一个值,它在布尔上下文中的计算结果为false,所以我们可以输入一点,并将你的例子减少到:

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

但是,如果该键中的值已定义但为“false”(数值计算为零,或者为空字符串),则可能导致误判,因此如果可能,我们应明确检查定义:

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

如果你不想自动审核$Table{$key1},你可以先检查它的存在,这会让我们看到一般案例的“最佳”方式

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

如果你要为哈希中的各个字段做很多事情,你可能想要添加一些OO风格的访问器方法,这些方法可以帮到你:

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

我确定你已经阅读过了,但再次阅读相关文档并不会有什么坏处:

  

给定一个指定哈希元素或数组元素的表达式,如果哈希值或数组中的指定元素已被初始化,则exists返回true,即使相应的值未定义。如果元素不存在,则该元素不会自动生成   ...
  散列或数组元素只有在定义时才为真,如果存在则定义,但反过来不一定适用。

答案 1 :(得分:6)

以下内容较短,可防止自动生成:

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

不需要代码中的其他检查。

答案 2 :(得分:1)

首先检查存在,然后检查定义。 (值可以不经定义而存在但不能在没有现有的情况下定义。)您应该使用exists测试中间级别以防止意外的自动更新。对于最后一级,您只需要致电defined。当没有太多层时,可以直接编码:

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

如果有很多层,这会变得很尴尬:

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

在这种情况下,您可以编写一个defined版本,该版本不会自动生成中间值:

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允许您构造任意数据 结构,就像标量引用数组的哈希......
  • 它不支持有福的引用(即对象)。

真正的通用版本留给读者练习。 ;)

答案 3 :(得分:1)

您可以查看Data::Diver。它潜入数据结构而不进行自动更新。语法如下:

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

甚至:

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

答案 4 :(得分:0)

大!谢谢大家的回复。

由于autvivifying对我来说是一个问题,目前我正在使用“尴尬”的方法,即 if(存在$ Table {$ key1}&& defined $ Table {$ key1} {$ key2}){

做任何事情

}

它适用于我,但正如你们所说,我有3-4级深度的嵌套哈希,代码有点乱。

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

再次感谢,