3

複雑なデータ構造は初めてです。それらの背後にある考え方はある程度理解していますが、データを取得するのに苦労しています。Data::Dumper を使用して、現在の問題児の構造を調べました....

$VAR1 = {
      '4' => {
               'engine_coded' => 0,
               'name' => 'FILTER_1',
               'filter_actions' => {
                                     'X_Override_Queue_Level' => 'Value'
                                   },
               'filter_criteria' => [
                                      [
                                        'X_Charge',
                                        '=',
                                        'X_CHARGE_1'
                                      ]
                                    ]
             }
    };

私がする必要があるのは、指定されたフィルター名 (この場合は「4」) が「name」に値、および「filter_actions」と「filter_criteria」があることを確認することです。

これを最もよく達成する方法を知っている人はいますか? どうもありがとう!ジャニー

4

3 に答える 3

5

これをバラバラに分解してみましょう...

まず、構造を検証する関数を作成します。

sub validate
{
    my ($data) = @_;

    # always return true for now
    return 1;
}

それでは、ビットの入力を開始しましょう... 検証チェックの一部としてフィルター名を使用したいので、それを引数として追加しましょう。

sub validate
{
    my ($data, $filter_name) = @_;

    # always return true for now
    return 1;
}

他のことを行う前に、そのフィルター名がキーとして存在するかどうかを確認することは理にかなっています。そうでない場合、検証は失敗しています:

sub validate
{
    my ($data, $filter_name) = @_;

    return if not exists $data->{$filter_name};

    # otherwise, return true
    return 1;
}

ここで、値があることも確認します。ハッシュキーの定義性は「存在する」のスーパーセットであるため (定義されている値はすべて存在する必要がありますが、存在するすべての値を定義する必要はありません - undef が値である可能性があるため)、最初のチェックは省略できます。

sub validate
{
    my ($data, $filter_name) = @_;

    return if not defined $data->{$filter_name};

    # otherwise, return true
    return 1;
}

filter_name キーがデータに存在し、定義されていることを確認しましたが、1 レベル深く調べる前に、それが本当に hashref であることを確認する必要があります。

sub validate
{
    my ($data, $filter_name) = @_;

    return if not defined $data->{$filter_name};

    return if ref $data->{$filter_name} ne 'HASH';

    # otherwise, return true
    return 1;
}

次に、フィルター名の下にある「filter_actions」キーと「filter_criteria」キーを探します。

sub validate
{
    my ($data, $filter_name) = @_;

    return if not defined $data->{$filter_name};

    return if ref $data->{$filter_name} ne 'HASH';

    return if not defined $data->{$filter_name}{filter_actions};
    return if not defined $data->{$filter_name}{filter_actions};

    # otherwise, return true
    return 1;
}

それでおしまい!perldoc perlreftootperldoc perlref、およびperldoc perldscでの perl データ構造の使用についてよく読んでください。

于 2011-02-04T18:06:38.443 に答える
0

これが私の見解です。フィルターにデータがあるかどうかを確認しているだけです。より構造的な検証が必要な場合は、その部分は後で行います。

use List::Util qw<first>;

sub validate_filter { 
    my ( $filters_ref, $filter_name ) = @_;
    my $filter  = $filter_name ? $filters_ref->{$filter_name} : $filters_ref;
    return 1 unless 
        my $missing 
            = first { !!$filter->{ $_ } } 
              qw<name filter_actions filter_criteria>
       ;
    if ( $missing ) { 
        Carp::croak( '"Missing '$missing' in filter!" );
    }
}

さて、私の最初の考えは、構造と名前を受け入れるだろうということでしたが、もちろん、あなたが呼び出すときに十分に知っていますか

validate_filter( $filters, 4 );

あなたは合格するのに十分知っています:

validate_filter( $filters->{4} );

そのため、パラメーター処理は最も理解しにくいかもしれませんが、パラメーターの受け渡しに関しては理にかなっています。

構造を検証した後であれば、このルートを選択できます。あなたのデータに基づいて、特定の filter_criteria クラスターに 3 番目のスロットごとに「=」演算子がない場合の検証失敗の例を示します。

そのようです:

use Carp       qw<croak>;
use List::Util qw<first>;
use Params::Util ();

sub _test { 
    return 1 if shift->( $_ );
    local $Carp::CarpLevel = $Carp::CarpLevel + 2;
    Carp::croak( shift );
}

my $validators 
    = { filter_actions => sub {
           croak 'filter_actions is not deinfed!' unless defined;
           _test( \&Params::Util::_HASH, 'filter_actions must be hash!' );
        }
      , filter_criters => sub {
            croak 'filter_criteria is not defined!' unless defined $crit;
            _test( \&Params::Util::_ARRAY, 'filter_criteria must be non-empty ARRAY!' );
            foreach ( @$crit ) { 
                _test( \&Params::Util::_ARRAY, 'criteria must be non-empty ARRAYs' );
                _test( sub { 
                           my $arr = shift;
                           return if @$arr % 3;
                           # return whether any slot in sequence is not '='
                           return !first { $arr->[$_] ne '=' } 
                                   # every 3 beginning at 1
                                   grep  { $_ % 3 == 1 } (1..$#$arr)
                                   ;
                       }
                     , 'criteria must be key-value pairs separated by equal sign!' 
                     );
            }
        }
    };

そして、これはvalidate_filterサブを次のように変更します:

sub validate_filter { 
    my ( $filters_ref, $filter_name ) = @_;
    my $filter  = $filter_name ? $filters_ref->{$filter_name} : $filters_ref;
    return 1 unless 
        my $missing 
            = first { 
                  return 1 unless $filter->{ $_ };
                  return   unless my $validator = $validators->{ $_ };
                  local $_ = $filter->{ $_ };
                  return 1 if $validator->( $_ );
              } 
              qw<name filter_actions filter_criteria>
       ;
    if ( $missing ) { 
        Carp::croak( "Missing '$missing' in filter!" );
    }
}
于 2011-02-04T19:12:09.827 に答える
0

filter_actionsをチェックすることで /etc にアクセスできます$var->{4}->{filter_actions}。perl のデータ構造の包括的な概要については、perldscを参照してください。

于 2011-02-04T18:04:10.500 に答える