estreb has asked for the wisdom of the Perl Monks concerning the following question:

Hello again, Monks. With the following code:
my %hash_of_hash_of_arrays = ( 'key' => { 'innerkey2' => [ 'here' ], 'innerkey3' => [ 'there' ], 'innerkey1' => [ 'hello', 'world' ] } );
I am trying to print each value in the hash ('here', 'there', 'hello', and 'world'). I tried the following, but it is giving me a syntax error in the second foreach loop:
foreach my $outerkey (keys %hash_of_hash_of_arrays) { print "'$outerkey'"; foreach my $innerkey (keys %hash_of_hash_of_arrays{$outerkey}) { print "\t'$hash_of_hash_of_arrays{$outerkey}{$innerkey}'"; foreach my $array_item (@{ $hash_of_hash_of_arrays{$outerkey}{$inn +erkey} }) { print "array item: $array_item"; } } }
The second foreach loop is incorrect. I have no idea if the third is even in the right ballpark. How do I fix this? Thanks in advance.

Replies are listed 'Best First'.
Re: printing all values in a hash of hashes of arrays
by toolic (Bishop) on Dec 15, 2014 at 19:26 UTC
    perldsc
    use warnings; use strict; my %hash_of_hash_of_arrays = ( 'key' => { 'innerkey2' => [ 'here' ], 'innerkey3' => [ 'there' ], 'innerkey1' => [ 'hello', 'world' ] } ); foreach my $outerkey (keys %hash_of_hash_of_arrays) { print "'$outerkey'\n"; foreach my $innerkey (keys %{ $hash_of_hash_of_arrays{$outerkey} }) +{ # <---- added curlies print "$innerkey\n"; foreach my $array_item (@{ $hash_of_hash_of_arrays{$outerkey}{$inn +erkey} }) { print "array item: $array_item\n"; } } } __END__ 'key' innerkey2 array item: here innerkey1 array item: hello array item: world innerkey3 array item: there

    For output order predictability, you can sort keys.

Re: printing all values in a hash of hashes of arrays
by GrandFather (Saint) on Dec 15, 2014 at 19:51 UTC

    Hashes and array elements are scalar values so can only hold references to nested hashes or arrays. Therefore hash_of_hash_of_arrays{$outerkey} is a reference to a hash. To get the hash you need for keys you need to dereference it using %{}: %{$hash_of_hash_of_arrays{$outerkey}}.

    Note that $, % and @ don't tell you what type variables are, they tell you what type of thing an expression returns. So $ref returns a scalar which may be a reference to an array or a hash. @$ref and @{$ref} return arrays (they are equivalent) by dereferencing $ref. The {} version is much clearer (and often required) when the expression used to get the reference is complicated.

    Perl is the programming world's equivalent of English

      Perl's own documentation on this subject is very good. (Refer to the section "Using References" of perldoc perlref

      Grandfather is recommending rule 2 because it always works. The other rules are essentially "short cuts" which apply in special cases.
      Bill
Re: printing all values in a hash of hashes of arrays
by CountZero (Bishop) on Dec 15, 2014 at 21:39 UTC
    Since Perl 5.14 this dereferencing is done automagically.

    From the docs:

    Starting with Perl 5.14, keys can take a scalar EXPR, which must contain a reference to an unblessed hash or array. The argument will be dereferenced automatically. This aspect of keys is considered highly experimental. The exact behaviour may change in a future version of Perl.
    1. for (keys $hashref) { ... }
    2. for (keys $obj->get_arrayref) { ... }

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics