如何在哈希中存储哈希哈希?

问题描述:

我在想,什么是在哈斯存储哈希哈希的最佳方式。让我们拿这样的哈希为例:如何在哈希中存储哈希哈希?

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

但我想保存这个在驼鹿属性。我应该如何组织访问(阅读,写作)。网上的例子大多是用于“平坦”的散列。但是,你可以使用像Moose :: Meta :: Attribute :: Native :: Trait :: Hash这样的助手。哈希值是否有类似的散列值?

这样做的原因是,我想迭代步进键并访问其中的对象实例。还是有更好的,更驼鹿般的方式来做到这一点?

在此先感谢!

可以在几乎相同的方式在一个木对象存储哈希散列,你会存储任何其他哈希:

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

和访问此我必须做这样的事'$对象 - >步骤() - > { '第一步} - > {' 提取'}'?但后来我可以改变价值,不是吗? – user1571117 2012-08-02 12:46:12

+0

上面的编辑有帮助吗? – zostay 2012-08-02 13:53:59

+0

是的,非常感谢 – user1571117 2012-08-02 14:23:47

还有一种类型安全的方法,通过Moose: How to get an array of objects? Traits?

启发有一个类来保存具有traits => ['Hash']的外部散列(StepTool :: Steps)。这种方法可以使用例如无限深嵌套。 Array S和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});