2012-08-02 10 views
4

해시 중 해시를 무스로 저장하는 가장 좋은 방법은 무엇입니까? 다음과 같이 해시를 예로들 수 있습니다.해시의 해시를 무스로 저장하는 방법?

my %hash = ('step1' => {'extraction' => \$object1, 
         'analysis' => \$object2}, 
      'step2' => {'extraction' => \$object3, 
         'analysis' => \$object4}); 

하지만이 하나를 무스 속성에 저장하고 싶습니다. 이것에 대한 접근 (읽기, 쓰기)을 어떻게 구성해야합니까? 그물의 예는 대부분 "평면"해시를위한 것입니다. 하지만 Moose :: Meta :: Attribute :: Native :: Trait :: Hash와 같은 도우미를 사용할 수 있습니다. 해시의 해시와 비슷한 것이 있습니까?

이유는 스텝 키를 반복하고 객체 인스턴스에 액세스하려고합니다. 아니면 이것을하는 더 나은, 더 무스와 같은 방법이 있습니까?

미리 감사드립니다.

당신이 다른 해시 저장하는 것과 같이 거의 같은 방법으로 무스 객체의 해시의 해시를 저장할 수

답변

10

: 당신은, 그러나, 특정로 선언하는 것이 더 구체적으로 할 수

has steps => (is => 'ro', isa => 'HashRef'); 

을 해당 슬롯에 저장된 것을 확인하는 방법으로 저장해야 해시의 종류는 일의 오른쪽 종류 :

has steps => (is => 'ro', isa => 'HashRef[HashRef[Object]]'); 

데이터에 따라, 나는 또한 클래스 이름에 여기 Object 변경 될 수 있습니다. 훨씬 더 까다로운 구조를 지정하기 위해서는 더 좋아질 수 있고 MooseX::TypesMooseX::Types::Structured을 사용할 수 있습니다.

도우미가 구조를 단계적으로 수행하는 데있어 Moose 또는 MooseX에서 아무 것도하지 않습니다. 데이터 구조를 아는 경우 자신이 필요로하는 것을 수행하기 위해 서브 루틴을 구현하는 것이 가장 좋습니다. 코드가 더 잘 수행되고 일반적인 트래버스보다 더 잘 수행 할 수 있습니다.

편집/추가 정보 : 각 무스 특성 때문에 데이터가 접근, 접근 방법을 저장된 값을 반환 어떤 클래스를 생성하지 :

# Assuming we put the attribute in a package named StepTool 
my $step_tool = StepTool->new(
    steps => { 'step1' => {'extraction' => \$object1, 
          'analysis' => \$object2}, 
       'step2' => {'extraction' => \$object3, 
          'analysis' => \$object4} }, 
); 

# To do something one of the values 
do_something($step_tool->steps->{step1}{extraction}); 

# To iterate over the structure, could be done in a method on StepTool 
for my $step_name (keys %{ $step_tool->steps }) { 
    my $step = $step_tool->steps->{ $step_name }; 

    for my $action_name (keys %$step) { 
     my $object = $step->{ $action_name }; 

     do_something($object); 
    } 
} 

# If doing the above as a method, $self is the Moose object, so... 
sub traverse_steps { 
    my ($self) = @_; 

    for my $step_name (keys %{ $self->steps }) { 
     ... # just like above 
    } 
} 

그리고 다른 한 노트, 당신은 여전히 ​​traits => [ 'Hash' ]을 사용할 수 있습니다 원하는 경우 일부 핸들을 추가하여 몇 가지 추가 도우미를 제공 할 수 있습니다.

데이터 구조가 이보다 더 자유로운 양식 인 경우 Data::Visitor과 같은 것을 조사하여 서브 루틴의 구조를 반복 할 수 있습니다. (나는 데이터 :: 방문자와 이상한 문제는, 디버그에 약간의 어려움이 있었다, 그래서 나는 때 내가 할 수있는 그것을 피하려고.)

+0

그리고 난이'$ 대상 - 같은 뭔가를해야이> 단계에 액세스 할 수() -> { '1 단계} -> {'추출 '}'? 하지만 그때 나는 가치로 변할 수 있니? – user1571117

+0

위의 편집이 도움이됩니까? – zostay

+0

네, 고맙습니다. – user1571117

0

도 있습니다 Moose: How to get an array of objects? Traits?

에서 영감을 형태 보증 된 접근 방식이있다 클래스를 사용하여 traits => ['Hash'] 인 외부 해시 (StepTool :: Steps)를 보유합니다. 이 접근법은 예를 들어를 사용하여 무한히 깊게 중첩 될 수있다. Array들과 Hash ES :

package StepTool; 

use Moose; 

has 'steps' => (
    'is' => 'rw', 
    'isa' => 'StepTool::Steps', 
    'default' => sub { StepTool::Steps->new() }, 
); 

package StepTool::Steps; 

use Mouse; 

has '_steps' => (
    is => 'ro', 
    isa => 'HashRef[StepTool::Step]', 
    traits => ['Hash'], 
    default => sub { {} }, 
    handles => { 
     # You'll probably want a fuller set here... 
     get => 'get', 
     set => 'set', 
     keys => 'keys', 
    } 
); 

package StepTool::Step; 

use Mouse; 

has 'extraction' => (
    is => 'rw', 
); 

has 'analysis' => (
    is => 'rw', 
); 

package main; 

my $object1 = bless {}, 'Foobar1'; 
my $object2 = bless {}, 'Foobar2'; 
my $object3 = bless {}, 'Foobar3'; 
my $object4 = bless {}, 'Foobar4'; 

my $stepTool = StepTool->new(); 

# set up step1 one field at a time. 
$stepTool->steps->set('step1', StepTool::Step->new()); 
# I have no idea why the OP wants references to objects 
# everywhere but he does... 
$stepTool->steps->get('step1')->extraction(\$object1); 
$stepTool->steps->get('step1')->analysis(\$object2); 

# set up step2 all at once 
$stepTool->steps->set('step2', StepTool::Step->new(
    extraction => \$object3, 
    analysis => \$object4 
)); 

# or, less elegantly, initialize an entire StepTool: 
my $stepTool2 = StepTool->new(
    steps => StepTool::Steps->new(
     _steps => { 
      step1 => StepTool::Step->new(
       extraction => \$object1, 
       analysis => \$object2 
      ), 
      step2 => StepTool::Step->new(
       extraction => \$object3, 
       analysis => \$object4 
      ), 
     } 
    ), 
); 

printf "step1->analysis is a ref to an instance of class: %s\n", 
    ref(${$stepTool->steps->get('step1')->analysis});