2011-02-04 37 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!"); 
    } 
}