2012-03-04 9 views
5

私はこの比較して検証したデータ構造

[ 
{ foo => { "<=" => 75 } }, 
{ bar => { "==" => 20 } }, 
{ baz => { ">=" => 5 } }, 
] 

などの条件を表現するハッシュリファレンスの配列リファレンスに対してこの1

{ foo => 65, bar => 20, baz => 15 } 

のようなハッシュリファレンスをチェックし、すべての条件が満たされた場合には、真の値を返すことがあります。

2つのデータ構造のどちらもあらかじめ決定されていません。 1つは、データベース内の文字列を解析し、もう1つはユーザー入力を解析することによって構築されます。上記の場合

最初のハッシュリファレンスでfooは= 60 <ではないので、私は、trueを返しますが、私は

[ 
{ foo => { "<=" => 60 } }, 
{ bar => { "==" => 20 } }, 
{ baz => { ">=" => 5 } }, 
] 

に対してハッシュリファレンスをチェックする場合、私はfalseを返します

質問は:それを行うための最善の戦略は何ですか?

私は< =、> =、5事前に構築された異なるsubrefs(>のためのケースごとに、<の間で適切なものと照合evalの
  • 経由subrefsのシリーズを構築

    • を考えています

      と==)

    私は間違った道を完全に下っていますか?そうでない場合は、最高、評価関数、または事前構築された関数は何ですか?

    私はParams :: Validateを調べましたが、オーバーヘッドが大きくなることが懸念され、とにかくコールバックを作成する必要があります。

  • +0

    重複したキーがある場合にのみ、単一のハッシュ・リファレンスの配列が役立ちます。例えば。 '' {{foo => ...}、{foo => ...}] '重複した鍵がないと思うので、これを冗長にするとハッシュを使い、配列をスキップするだけです。 – TLP

    答えて

    7

    代わりにコード参照を使用すると、バリデーターの準備が整います。私はあなたの条件構造を単純化しました。ハッシュ・キーが重複していない限り、余分な配列レベルを持つ必要はありません。

    簡略化したsub { $_[0] <= 75 }は、単に引数の最初の値を比較します。デフォルトでは、サブルーチンで評価された最後の値は戻り値になります。

    use v5.10; 
    use strict; 
    use warnings; 
    
    my $in = { foo => 65, bar => 21, baz => 15 }; 
    
    my $ref = { 
        foo => sub { $_[0] <= 75 } , 
        bar => sub { $_[0] == 20 } , 
        baz => sub { $_[0] >= 5 } , 
    }; 
    
    for my $key (keys %$in) { 
        if ($ref->{$key}($in->{$key})) { 
         say "$key : Valid"; 
        } else { 
         say "$key : Invalid"; 
        } 
    } 
    

    出力:

    bar : Invalid 
    baz : Valid 
    foo : Valid 
    
    +0

    答えをありがとう。 – simone

    +0

    @simoneよろしくお願いします。 – TLP

    1

    TLPの答えに構築するには、あなたも簡単に既存のアレイ・オブ・ハッシュから匿名サブルーチンを作成することができます。

    my $array_of_hashes = [ 
        { foo => { "<=" => 75 } }, 
        { bar => { "==" => 20 } }, 
        { baz => { ">=" => 5 } }, 
    ]; 
    
    my $ref = {}; 
    foreach my $entry (@$array_of_hashes) { 
        my ($key, $subhash) = %$entry; 
        my ($op, $num) = %$subhash; 
        $ref->{$key} = { 
         '<=' => sub { $_[0] <= $num }, 
         '==' => sub { $_[0] == $num }, 
         '>=' => sub { $_[0] >= $num }, 
        }->{$op}; 
    } 
    

    これは想定していオリジナルのハッシュ配列で各フィールドのチェックを1つだけ行うことができます。あなたは、いくつかを持っている可能性がある場合は、物事は少しトリッキー得るが、あなたは常にこのような何か行うことができます:

    my $ref = {}; 
    foreach my $entry (@$array_of_hashes) { 
        my ($key, $subhash) = %$entry; 
        my ($op, $num) = %$subhash; 
        my $chain = $ref->{$key} || sub {1}; 
        $ref->{$key} = { 
         '<=' => sub { $_[0] <= $num and $chain->($_[0]) }, 
         '==' => sub { $_[0] == $num and $chain->($_[0]) }, 
         '>=' => sub { $_[0] >= $num and $chain->($_[0]) }, 
        }->{$op} || $chain; 
    } 
    

    PSは。このコードがどのように機能するか疑問に思っている人は、答えはclosuresです。具体的には、これらの匿名サブがループ内で作成された場合、これらの変数がループの現在の反復の終わりにスコープから外れた後でも、字句変数$numおよび$chainへの参照を保持します。だから、永遠にそれらの変数は、私たちが作成したサブルーチンからしかアクセスできない、安全に掘り下げられます。

    関連する問題