5

ハッシュ要素の Perl ハッシュが$Table{$key1}{$key2}存在し、定義されていることなどを検証する必要があります。これが私がすることです。($key1存在すら知らん)

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

それを行うためのより簡単でクリーンな方法はありますか?

4

5 に答える 5

8

階層の各レベルをチェックする必要はありません。関心のある値を選択するだけでかまいません。existsハッシュ内のスロットが存在する場合のみ (未定義の値で存在する可能性があります)、定義されているかどうかをチェックしません。したがって、値が定義されていることを気にする場合はdefined、存在するのではなく呼び出す必要があります。値が定義されていない場合、ブール値のコンテキストで false と評価されるため、入力を少し減らして例を次のように減らすことができます。

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

ただし、そのキーの値が定義されているが「false」(数値的にゼロに評価されるか、空の文字列である) である場合、これは偽陰性を引き起こす可能性があるため、可能性がある場合は定義されているかどうかを明示的に確認する必要があります。

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 を返します。要素が存在しない場合、その要素は自動有効化されません。
...
ハッシュまたは配列要素は、定義されている場合にのみ true になり、存在する場合に定義されますが、その逆は必ずしも true とは限りません。

于 2010-04-27T17:42:25.070 に答える
6

以下は短く、autovivication から保護します。

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

コード内の他のチェックは必要ありません。

于 2010-04-27T17:46:27.440 に答える
1

Data::Diverをチェックアウトできます。自動活性化せずにデータ構造に飛び込みます。構文は次のようになります。

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

あるいは:

if ( defined(my $value = Dive(\%Table, $key1, $key2) ) ) {
  ...do something with $value...
}
于 2010-04-27T21:47:42.137 に答える
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 では、スカラー参照の配列のハッシュなど、任意のデータ構造を作成できます...
  • 祝福された参照 (つまり、オブジェクト) はサポートしていません。

真に一般的なバージョンは、読者の演習として残されています。;)

于 2010-04-27T19:39:30.243 に答える
0

すごい!返信ありがとうございます。

自動有効化は私にとって問題であるため、現在、「厄介な」アプローチを使用しています。つまり、if (exists $Table{$key1} && defined $Table{$key1}{$key2}) {

何でもする

}

それは私にとってはうまくいきますが、皆さんが言ったように、ネストされたハッシュの深さが3〜4レベルあり、コードは少し面倒です。

Data:Diver を調べてみます。そっちの方がよさそうです。

再度、感謝します、

于 2010-04-28T17:34:50.073 に答える