2013-07-16 36 views
1

我完全陷进去了一个问题:如何切换多哈希表在Perl

我有几个巨大的多层次hash_tables一些巨大的Perl脚本。 一切工作正常,但为了减少代码和可读性,我想将最后一个散列引用交给子函数。

如前所述,我确实有几个不同的散列表,例如, %hash_table1和%hash_table2,都具有相同的值,但密钥的级别不同。

hash_table1用3级键:

$hash_table1{$key1}{$key2}{$key3}->{value1} 
$hash_table1{$key1}{$key2}{$key3}->{value2} 
$hash_table1{$key1}{$key2}{$key3}->{value3} 

我有在其他hash_table相同的 “值”,但使用不同的多级: hash_table2用2级键:

$hash_table2{$key1}{$key2}->{value1} 
$hash_table2{$key1}{$key2}->{value2} 
$hash_table2{$key1}{$key2}->{value3} 

我可以很容易地访问所有的值分别通过只是复制过去的所有代码,改变它的密钥量,但大多数时候,我确实有20个不同的值,所以...访问数据的代码量是......很好......很大。此外,如果需要更改某些东西,我将不得不多次更改它(

我想要的是类似以下子函数,其中我基本上只是将最后一个散列键引用存储在一个临时散列表可以方便地访问不同的哈希表中的所有值以同样的方式(这是一个不正常的部分!):

sub print_all_values { 
    my %hash_tmp = shift @_; 
    printf $hash_tmp->{value1}.";"; 
    printf $hash_tmp->{value2}.";"; 
    printf $hash_tmp->{value3}."\n"; 
} 

,并在某处我通过多级系统处理代码,只是通过最后引用前面定义的子函数来做...以及那里应该用存储的值做什么(可以说只是打印):

foreach my $k1 (sort {$a <=> $b} keys %hash_table1){ 
    foreach my $k2 (sort {$a <=> $b} keys %{$hash_table1{$k1}}){ 
     foreach my $k3 (sort {$a <=> $b} keys %{$hash_table1{$k1}{$k2}} 
     print_all_values(%{$hash_table1{$k1}{$k2}{$k3}}); 
     } 
    } 
} 

末别的地方的代码来访问二级hash_table:

foreach my $k1 (sort {$a <=> $b} keys %hash_table2){ 
    foreach my $k2 (sort {$a <=> $b} keys %{$hash_table2{$k1}}){ 
     print_all_values(%{$hash_table2{$k1}{$k2}}); 
    } 
} 

正如前面提到的,这纯粹是好的,有一个有效的解决方案通过在过去的散列引用到子功能基本上一次访问所有存储的值。

提前为任何有帮助的评论非常感谢,

一切顺利,

OldMcFunsy

+0

哎呀!这使我的大脑受伤。这个解决方案正在呼吁[面向对象方法](http://perldoc.perl.org/perlootut.html)。这将有助于保持所有散列密钥同步。给我多一些关于各种键代表什么的信息,我可能会得到一个快速的答案。面向对象将帮助您处理这些密钥和散列级别的混乱,并让您的代码更清洁,更易于维护。 –

+0

'%hash_tmp'和'$ hash_tmp - > {key}'不是指同一个散列! – mob

回答

1

看看perlref

你应该只是传递到子的参考:

print_all_values(\%hash_table); 

sub print_all_values { 
    my $hash_tmp = shift; 
    printf $hash_tmp->{value1}.";"; 
    printf $hash_tmp->{value2}.";"; 
    printf $hash_tmp->{value3}."\n"; 
} 
+0

非常感谢,我永远不会有关于声明我的hash_tmp作为参考,而不是作为hash_table。只是从%更改为$。你无法想象我花了多少小时来尝试这段代码的工作。非常感谢!!! – user2588230

0
sub print_all_values { 
    print(join(";", @_), "\n"); 
} 

for my $k1 (sort {$a <=> $b} keys %hash_table1) { 
    for my $k2 (sort {$a <=> $b} keys %{ $hash_table1{$k1} }) { 
     print_all_values(
     @{ $hash_table1{$k1}{$k2} }{ 
      sort {$a <=> $b} keys %{ $hash_table1{$k1}{$k2} } 
     } 
    ); 
    } 
} 

对不起,没时间解释。

+0

嗨,谢谢你们,这两种解决方案都能够满足我的要求。 你无法想象我花了多少小时来解决问题! – user2588230

0
sub print_all_values { 
    my %hash_tmp = shift @_; 
    printf $hash_tmp->{value1}.";"; 
    printf $hash_tmp->{value2}.";"; 
    printf $hash_tmp->{value3}."\n"; 
} 

$hash_tmp->{value1}被引用的东西从%hash_tmp完全独立。将这些更改为$hash_tmp{value1}可能会解决此问题。另外,总是使用严格和警告。

0

这应该工作,但我没有任何复杂的哈希来测试它。 :)

# -------------------------------------- 
#  Name: scan_hash 
#  Usage: %value_of = scan_hash(\%hash_tree, @keys); 
# Purpose: To do a depth first scan of the hash tree 
#    and create a hash of the leaves. 
# Parameters: \%hash_tree -- Tree to scan 
#     @keys -- List of keys; these may appear anywhere in the tree 
# Returns: %value_of -- a simple key=>value has, 
#       the keys are from @keys 
#       and their values are what was found 
# 
sub scan_hash { 
    my $hash_tree = shift @_; 
    my @keys  = @_; 
    my %value_of =(); 

    for my $key (keys %$hash_tree){ 

    # save if the current key is one we're looking for 
    if(grep { $_ eq $key } @keys){ 
     $value_of{$key} = $hash_tree->{$key}; 

    # is it a reference? 
    }elsif(my $ref = ref($hash_tree->{$key})){ 

     if($ref eq 'HASH'){ 

     # hash references are scanned via recursion 
     my %new_value_of = scan_hash($hash_tree->{$key}, @keys); 

     # stored using slices: http://perldoc.perl.org/perldata.html#Slices 
     @value_of{ keys %new_value_of } = values %new_value_of; 

     }else{ 
     die "cannot handle a $ref reference\n"; 
     } 

    } # end if 

    } # end for 

    return %value_of; 
}