2010-04-27 73 views
5

我需要驗證散列元素的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

回答

8

你不需要檢查每個等級的等級:你可以爲你關心的價值。 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

5

以下是短,從autovivifcation將保護:不需要

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

在你的代碼的其他檢查。

1

檢查存在,然後再定義的煩躁。 (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中,您可以構造任意的數據 結構,像標引用數組的哈希...
  • 它不支持有福引用(即對象)。

一個真正的通用版本就留給讀者自己練習。 ;)

1

你可以檢查出Data::Diver。它沒有autovivifying潛入數據結構。語法是:

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

甚至:

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

太好了!謝謝大家的回覆。

由於autovivifying對我來說是一個問題,目前我使用的是 「尷尬」 的方式,即 如果(存在$表{$鍵1} & &定義$表{$鍵1} {$鍵2}){

什麼就做什麼

}

它爲我,但是作爲你們說的,我有3-4級深度嵌套散列,代碼凌亂位。

我會檢查出數據:潛水員。那個看起來更好。

再次感謝,

相關問題