4

ハッシュの配列があり、すべて同じキーのセットがあります。例:

my $aoa= [
 {NAME=>'Dave', AGE=>12, SEX=>'M', ID=>123456, NATIONALITY=>'Swedish'},
 {NAME=>'Susan', AGE=>36, SEX=>'F', ID=>543210, NATIONALITY=>'Swedish'},
 {NAME=>'Bart', AGE=>120, SEX=>'M', ID=>987654, NATIONALITY=>'British'},
]

指定されたキー階層を使用して、これをハッシュのハッシュに変換するサブルーチンを作成したいと思います。

my $key_hierarchy_a = ['SEX', 'NATIONALITY'];
aoh_to_hoh ($aoa, $key_hierarchy_a) = @_;
 ...
}

戻ります

{M=>
  {Swedish=>{{NAME=>'Dave', AGE=>12, ID=>123456}},
   British=>{{NAME=>'Bart', AGE=>120, ID=>987654}}}, 
 F=>
  {Swedish=>{{NAME=>'Susan', AGE=>36,  ID=>543210}}
}

これにより、正しいキー階層が作成されるだけでなく、冗長になったキーも削除されることに注意してください。

正しい階層位置に新しい最も内側のハッシュを作成する必要がある時点で行き詰まっています。

問題は、「深さ」(つまり、キーの数)がわからないことです。私が定数を持っている場合、私は次のようなことをすることができます:

%h{$inner_hash{$PRIMARY_KEY}}{$inner_hash{$SECONDARY_KEY}}{...} = filter_copy($inner_hash,[$PRIMARY_KEY,$SECONDARY_KEY])

したがって、残りのハッシュを「現在の」場所に追加するよりも、一度に1つのレベルを追加し、ハッシュからそのキーを削除するループを作成できるかもしれませんが、少し面倒であり、維持する方法もわかりません。ハッシュのハッシュ内の「場所」..

4

2 に答える 2

6
use Data::Dumper;

my $aoa= [
 {NAME=>'Dave', AGE=>12, SEX=>'M', ID=>123456, NATIONALITY=>'Swedish'},
 {NAME=>'Susan', AGE=>36, SEX=>'F', ID=>543210, NATIONALITY=>'Swedish'},
 {NAME=>'Bart', AGE=>120, SEX=>'M', ID=>987654, NATIONALITY=>'British'},
];

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
                                  }
                                ]
                 }
        };

編集:ああ、ところで-誰かが参照の内容をエレガントに複製する方法を知っているなら、教えてください。ありがとう!

編集編集:@FMが役に立ちました。今はもっと良い:D

于 2010-10-03T13:37:57.250 に答える
2

経験したように、任意の深さのハッシュ構造を作成するコードを書くのは少し注意が必要です。そして、そのような構造にアクセスするためのコードも同様にトリッキーです。不思議に思うのは、本当にこれを実行したいのかということです。

より簡単なアプローチは、元の情報をデータベースに入れることかもしれません。関心のあるキーにインデックスが付けられている限り、DBエンジンは関心のある行を非常に迅速に取得できます。SEX=女性、NATIONALITY=スウェーデンのすべての人を教えてください。今ではそれは有望に聞こえます!

また、このゆるやかに関連する興味のある質問を見つけるかもしれません。

于 2010-10-03T14:26:54.110 に答える