我有一系列哈希,都有相同的密钥集,例如:
my $aoa= [ {NAME=>'Dave',AGE=>12,SEX=>'M',ID=>123456,NATIONALITY=>'Swedish'},{NAME=>'Susan',AGE=>36,SEX=>'F',ID=>543210,{NAME=>'Bart',AGE=>120,ID=>987654,NATIONALITY=>'British'},]
我想编写一个子程序,它将使用给定的键层次结构将其转换为哈希哈希值:
my $key_hierarchy_a = ['SEX','NATIONALITY']; aoh_to_hoh ($aoa,$key_hierarchy_a) = @_; ... }
将返回
{M=> {Swedish=>{{NAME=>'Dave',ID=>123456}},British=>{{NAME=>'Bart',ID=>987654}}},F=> {Swedish=>{{NAME=>'Susan',ID=>543210}} }
请注意,这不仅会创建正确的密钥层次结构,还会删除现在的冗余密钥.
我陷入困境,需要在正确的分层位置创建新的,最内部的哈希.
问题是我不知道“深度”(即键的数量).如果我有一个常数,我可以这样做:
%h{$inner_hash{$PRIMARY_KEY}}{$inner_hash{$SECONDARY_KEY}}{...} = filter_copy($inner_hash,[$PRIMARY_KEY,$SECONDARY_KEY])
所以也许我可以编写一个循环,一次添加一个级别,从散列中删除该键,而不是将剩余的散列添加到“当前”位置,但它有点麻烦,我也不知道如何保持哈希散列中的“位置”……
解决方法
use Data::Dumper; my $aoa= [ {NAME=>'Dave',]; sub aoh_to_hoh { my ($aoa,$key_hierarchy_a) = @_; my $result = {}; my $last_key = $key_hierarchy_a->[-1]; foreach my $orig_element (@$aoa) { my $cur = $result; # song and dance to clone an element my %element = %$orig_element; foreach my $key (@$key_hierarchy_a) { my $value = delete $element{$key}; if ($key eq $last_key) { $cur->{$value} ||= []; push @{$cur->{$value}},\%element; } else { $cur->{$value} ||= {}; $cur = $cur->{$value}; } } } return $result; } my $key_hierarchy_a = ['SEX','NATIONALITY']; print Dumper(aoh_to_hoh($aoa,$key_hierarchy_a));
根据@ FM的评论,你真的想要一个额外的数组级别.
输出:
$VAR1 = { 'F' => { 'Swedish' => [ { 'ID' => 543210,'NAME' => 'Susan','AGE' => 36 } ] },'M' => { 'British' => [ { 'ID' => 987654,'NAME' => 'Bart','AGE' => 120 } ],'Swedish' => [ { 'ID' => 123456,'NAME' => 'Dave','AGE' => 12 } ] } };
编辑:哦,BTW – 如果有人知道如何优雅地克隆参考的内容,请教.谢谢!
编辑编辑:@FM帮助.现在好多了:D