2011-02-04 6 views
3

복잡한 데이터 구조가 생소합니다. 나는 그 (것)들의 뒤에 아이디어를 이해하고 그러나 데이터를 꺼내는 약간 어려움이 있고있다. 나는 내가 무엇을 필요로하고하는 것은 ("이 경우"4 ") 필터 이름을 부여해야 할 것입니다Perl : 복잡한 데이터 구조의 요소 계산하기

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

.... 데이터 : 덤퍼를 사용하여 내 현재의 문제를 아이의 구조를 발견 "이름은"값뿐만 아니라 아이디어가

누구든지 최선의 방법이 작업을 수행하기 위해 "filter_actions"와 "filter_criteria".? 많은 감사를 가지고! 제이니

+0

는 당신이 실제로 요구하는 것과 일치하는 - 당신이 어디에 필요한가를 요소를 계산합니까? – Ether

답변

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

+0

@DVK : 전화하세요. – Ether

+0

더 간단한 방법은'ref (MY_DAYA_STRUCT) ne ref ({}))' – DVK

0

을 당신이 선택하여 filter_actions/등을 액세스 할 수 있습니다 $var->{4}->{filter_actions} perl의 데이터 구조에 대한 포괄적 인 개요는 perldsc을 참조하십시오.

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!"); 
    } 
} 
관련 문제