[英]Perl: Counting elements in a complex data structure
我是復雜數據結構的新手。 我有點理解他們背后的想法,但是在獲取數據方面遇到了一些困難。 我通過使用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”。
任何人都知道如何最好地完成這個? 非常感謝! 珍妮
讓我們分解成碎片......
首先,創建一個驗證結構的函數:
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可能是值),可以省略第一個檢查:
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數據結構的內容。
您可以通過檢查$var->{4}->{filter_actions}
來訪問filter_actions
/ $var->{4}->{filter_actions}
您可以查看perldsc以全面了解perl的數據結構。
這是我的看法。 您只是檢查過濾器中是否有數據。 如果你想要更多的結構驗證,那么這部分就會出現
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!" );
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.