Perl: подсчет элементов в сложной структуре данных - PullRequest
3 голосов
/ 04 февраля 2011

Я новичок в сложных структурах данных. Я вроде понимаю идею, стоящую за ними, но испытываю некоторые затруднения при получении данных. Я узнал структуру моего текущего проблемного ребенка, используя 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».

У кого-нибудь есть идеи, как лучше всего это сделать? Большое спасибо! Джени

Ответы [ 3 ]

5 голосов
/ 04 февраля 2011

Давайте разберем это на части ...

Сначала создайте функцию, которая проверяет структуру:

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 присутствует в данных и он определен, но прежде чем заглянуть на один уровень глубже, мы должны подтвердить, что это действительно хеш-код:

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;
}

Вот и все! Обязательно прочитайте об использовании структур данных perl в perldoc perlreftoot , perldoc perlref и perldoc perldsc .

0 голосов
/ 04 февраля 2011

Вот мой дубль.Вы просто проверяете, есть ли данные в фильтре.Если вам нужна дополнительная структурная проверка, эта часть появится позже.

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!" );
    }
}
0 голосов
/ 04 февраля 2011

Вы можете получить доступ к filter_actions / etc, установив $var->{4}->{filter_actions}. Вы можете посмотреть на perldsc для полного обзора структур данных perl.

...