How to extract key name from a hash of hash?

2019-07-11 21:21发布

问题:

I have following hash of hash :

%HoH = (
flintstones => {
    husband   => "fred",
    pal       => "barney",
},
jetsons => {
    husband   => "george",
    wife      => "jane",
    his boy => "elroy", 
},
simpsons => {
    husband   => "homer",
    wife      => "marge",
    kid       => "bart",
},

);

How to iterate over each inner hash (say flintstones) and also extract the key names (husband, pal) and corresponding vales for each such iteration?

回答1:

for my $k (keys %{ $HoH{flintstones} }) {

  my $v = $HoH{flintstones}{$k};
  print "key is $k; value is $v\n";
}

another way would be using each

while( my($k, $v) = each %{ $HoH{flintstones} }) { ... }


回答2:

for my $outer_key ( keys %HoH )
   {
   print "Values for inner_hash $outer_key:\n";
   for my $inner_key ( keys %{$HoH{$outer_key}} )
      {
      print "\t'$inner_key' points to " . $HoH{$outer_key}{$inner_key} .  "\n";
      }
   }

Because each key in the outer level points to a hash in the inner level we can use all the normal hash functions on that entry.

While it is possible to write this in a more succinct way without the double loop I prefer the nested loops for two reasons.

  1. It is more obvious when someone else has to work on the code (including you in six months as someone else).

  2. It makes it easier to track things such as which outer key leads to this point if needed (as shown in my output).



回答3:

Just loop over the hash (by keys or values or each, depending on whether you need the keys and on taste) and then loop over the inner hashes (likewise).

So, to get all of the people described by this hash:

for (values %HoH) {
  for (values $_) {
    push @people, $_
  }
}

Or to build a table of all the husbands, all the wives, etc.:

for my $fam (values %HoH) {
  push @{$relations{$_}}, $fam->{$_} for keys $fam
}

Or to re-key the table off the husbands:

for my $fam (keys %HoH) {
  $patriarchs{$HoH{$fam}{husband}}{family} = $fam;
  for (keys $HoH{$fam}) {
    next if $_ eq 'husband';
    $patriarchs{$HoH{$fam}{husband}}{$_} = $HoH{$fam}{$_};
  }
}