我是复杂数据结构的新手。我有点理解他们背后的想法,但是在获取数据方面遇到了一些困难。我通过使用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”。
任何人都知道如何最好地完成这项工作?非常感谢! 珍妮
答案 0 :(得分: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;
}
现在还检查是否有值。由于散列键中的定义是'exists'的超集(定义的任何值也必须存在,但不是每个存在的值都需要定义 - 因为undef可能是值),可以省略第一个检查:< / p>
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 perlref和perldoc perldsc中使用perl数据结构的内容。
答案 1 :(得分:0)
您可以通过查看filter_actions
来访问$var->{4}->{filter_actions}
/ etc。您可以查看perldsc以获取有关perl数据结构的全面概述。
答案 2 :(得分: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,如此:
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!" );
}
}