2017-05-30 9 views
0

私はPerlで多次元ハッシュの値を持っています。多次元ハッシュの第1レベルキーの検索Perl

その構造は、私が正しい値とフィールドの両方を持っていることを考えると

$hash{$key}{$field}{$date} = $value; 

です。

EDIT(キーに1-1関係を有する)の値自体が一意であることを考えると、そのキーに検索することができる最速の方法は何ですか:

Iは第3のレベルを追加しました日付です。 すべての日付に値があるわけではありませんが、表示された日付はすべての日付で共有されます。

簡略化するため、値がある場合は「A」、それ以外は空白です。

よろしく、

+0

'$ハッシュ{$ _} {$フィールド} EQ $値と印刷「=> $ _を\最初のレベルのキーを検索している場合は、キー%hash; –

+0

「印刷して最後に」欲しいかもしれません。 – Sobrique

+0

はい、また定期的にforeachをブロックします(btw、条件を満たす複数の第1レベルキーがあるかもしれません)。 –

答えて

4

InnZaayynnあなたのデータの編成は、高速検索を行うには適していません。ハッシュ全体を反復処理する必要があります。複数の検索を実行する場合は、「逆」ハッシュを生成するのが一番です。そのため、検索ごとに1回ではなく、ハッシュ全体を1回だけ繰り返す必要があります。


あなたが複数の検索を実行している、と彼らは同じフィールドのすべてのいない場合は、次のように逆ハッシュを生成します。

my %key_by_field_and_value; 
for my $key (keys(%hash)) { 
    my $hash_for_key = $hash{$key}; 
    for my $field (keys(%$hash_for_key)) { 
     my $hash_for_key_and_field = $hash_for_key->{$field}; 
     defined(my $date = get_any_one_key($hash_for_key_and_field)) 
     or next; 

     length(my $value = $hash_for_key_and_field->{$date}) 
     or next; 

     $key_by_field_and_value{$field}{$value} = $key; 
    } 
} 

そして、検索が

my $field  = ...; 
my $target_value = ...; 

if (defined(
    my $target_key = 
     do { no autovivification; $key_by_field_and_value{$field}{$target_value} } 
)) { 
    ... 
} 
なり

複数の検索を実行しており、すべてが同じフィールドの場合は、次のように逆ハッシュを生成します。

my $field = ...; 

my %key_by_value; 
for my $key (keys(%hash)) { 
    my $hash_for_key = $hash{$key}; 
    defined(my $hash_for_key_and_field = $hash_for_key->{$field}) 
     or next; 

    defined(my $date = get_any_one_key($hash_for_key_and_field)) 
     or next; 

    length(my $value = $hash_for_key_and_field->{$date}) 
     or next; 

    $key_by_value{$value} = $key; 
} 

そして、検索は、あなたが一度だけ検索するつもりなら、あなたは全体のハッシュを検索する必要があります

my $target_value = ...; 

if (defined(my $target_key = $key_by_value{$target_value})) { 
    ... 
} 

になります。上記溶液の

my $field  = ...; 
my $target_value = ...; 

my $target_key; 
for my $key (keys(%hash)) { 
    my $hash_for_key = $hash{$key}; 
    defined(my $hash_for_key_and_field = $hash_for_key->{$field}) 
     or next; 

    defined(my $date = get_any_one_key($hash_for_key_and_field)) 
     or next; 

    length(my $value = $hash_for_key_and_field->{$date}) 
     or next; 

    if ($value eq $target_value) { 
     $target_key = $key; 
     last; 
    } 
} 

if (defined($target_key)) { 
    ... 
} 

両方my ($key) = keys(%$h);のこの効率的なバージョンの使用:

sub get_any_one_key { 
    my ($h) = @_; 
    my $key = each(%$h); 
    keys(%$h); # Reset iterator 
    return $key; 
} 
関連する問題