2011-02-04 84 views
3

我是新来的复杂数据结构。我有点理解他们背后的想法,但在获取数据时遇到了一些困难。我发现我现在的问题孩子的结构,通过使用数据::自卸车....Perl:计算复杂数据结构中的元素

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

什么,我需要做的是确保(在这种情况下,“4”“)给出的过滤器的名称认为“名”有一个值,以及“filter_actions”和“filter_criteria”。

人有一个想法如何最好地做到这一点?非常感谢! 珍妮

+0

问题标题似乎并不符合您实际要求 - 你在哪里需要计数元素? – Ether 2011-02-04 18:10:08

回答

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关键是存在于数据,并将其定义,但寻找一个更深层次之前,我们需要确认它真的是一个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 perlreftoot,perldoc perlrefperldoc perldsc中的perl数据结构。

+0

你也许应该检查$ data - > {filetername}是一个hashref。 – DVK 2011-02-04 18:15:51

0

您可以通过检查访问filter_actions的/ etc $var->{4}->{filter_actions}。您可能会看到perldsc以获取perl数据结构的全面概述。

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!"); 
    } 
}