2012-04-28 2 views
3

임의로 큰 중첩 구조의 해시 및 배열을 스캔하고 단일 값에 대한 참조로 모든 동일한 분기 (예 : Test::Deep::cmp_deeply이 'ok'라고 말한 모듈)를 대체 할 수있는 Perl 용 모듈을 즉시 사용할 수 있습니까?중첩 구조 내부의 동일한 분기를 참조로 신속하게 대체하는 방법은 무엇입니까?

이 문제에 대한 내 자신의 솔루션이 이미 있지만 사용할 수있는 경우 기존 빠른 XS 모듈을 사용하는 것이 좋습니다. Data::Dumper 같이 원래 구조의

예 : 예상 된 결과 구조의

$VAR1 = { 
    'other_elems' => [ 
     { 
      'sub_elements' => [ 
       {'id' => 333}, 
       { 
        'props' => ['attr5', 'attr6'], 
        'id' => 444 
       } 
      ], 
      'other_key_for_attrs' => ['attr1', 'attr5'], 
      'id'     => 222 
     }, 
     { 
      'sub_elements' => [{'id' => 333}], 
      'id'   => 111 
     } 
    ], 
    'elems' => [ 
     { 
      'attrs' => ['attr1', 'attr5'], 
      'id' => 1 
     }, 
     { 
      'parent' => 3, 
      'attrs' => ['attr1', 'attr5'], 
      'id'  => 2 
     }, 
     { 
      'attrs' => ['attr5', 'attr6'], 
      'id' => 3 
     }, 
     { 
      'attrs' => ['attr5', 'attr6'], 
      'id' => 4 
     } 
    ] 
}; 

예 :

$VAR1 = { 
    'other_elems' => [ 
     { 
      'sub_elements' => [ 
       {'id' => 333}, 
       { 
        'props' => ['attr5', 'attr6'], 
        'id' => 444 
       } 
      ], 
      'other_key_for_attrs' => ['attr1', 'attr5'], 
      'id'     => 222 
     }, 
     { 
      'sub_elements' => 
       [$VAR1->{'other_elems'}[0]{'sub_elements'}[0]], 
      'id' => 111 
     } 
    ], 
    'elems' => [ 
     { 
      'attrs' => $VAR1->{'other_elems'}[0]{'other_key_for_attrs'}, 
      'id' => 1 
     }, 
     { 
      'parent' => 3, 
      'attrs' => $VAR1->{'other_elems'}[0]{'other_key_for_attrs'}, 
      'id'  => 2 
     }, 
     { 
      'attrs' => 
       $VAR1->{'other_elems'}[0]{'sub_elements'}[1]{'props'}, 
      'id' => 3 
     }, 
     { 
      'attrs' => 
       $VAR1->{'other_elems'}[0]{'sub_elements'}[1]{'props'}, 
      'id' => 4 
     } 
    ] 
}; 

답변

2

나는 이러한 모듈의 모르겠지만, 작업이 너무 재미 같은 소리 나는 비교를 위해서 당신에게 나의 구현을 줄 것이다. 이것은 직렬화 작업이 데이터 구조를 따라갈 때 중복되므로 비효율적입니다 (리프 요소에서 위쪽으로 이동하여 직렬화 된 문자열을 구성하는 것처럼 다시 작성할 수 있음).

#!/usr/bin/env perl 
use warnings; 
use strict; 

use Data::Dumper; 

my $hash = { 
    foo => ['bar', {baz => 3}], 
    qux => [{baz => 3}, ['bar', {baz => 3}]] 
}; 

{ 
    local $Data::Dumper::Sortkeys = 1; 
    local $Data::Dumper::Indent = 0; 
    local $Data::Dumper::Terse = 1; 

    my %seen_branches; 
    my @refs_to_check = \(values %$hash); 
    while (my $ref = shift @refs_to_check) { 
     my $serial = Dumper($$ref); 
     if (my $existing = $seen_branches{$serial}) { 
      $$ref = $existing; 
     } else { 
      $seen_branches{$serial} = $$ref; 
      if (ref($$ref) eq 'ARRAY') { 
       push @refs_to_check, \(@{$$ref}); 
      } elsif (ref($$ref) eq 'HASH') { 
       push @refs_to_check, \(values %{$$ref}); 
      } 
     } 
    } 
} 

print Dumper $hash;