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

Pretty newbie, so I'm sure you can all answer this :)

I want to run a foreach on all the elements of all the hashes nested within a hash. Just now, however, I'm having difficulty accessing them.

Here's the code, and you'll see the bit that's going wrong. Help!

#!/usr/bin/perl -w my %termservers = ( TERM192_168_0_1 => { CE_36xx101 => "PORT_2047", CE_36xx122 => "PORT_2060", CE_36xx124 => "PORT_2062" }, TERM192_168_0_2 => { CE_26xx103 => "PORT_2012", CE_26xx109 => "PORT_2014" } ); foreach my $key (keys %termservers) { print "1 $key \n"; #works# print "2 $termservers{$key}\n"; #prints hash_ref# print "3", keys({%termservers{$key}}), "\n"; #doesn't work# };
toeslikefingers.com - because you've got too much time on your hands

Replies are listed 'Best First'.
Re: Hash of hashes question
by ChrisR (Hermit) on Oct 22, 2003 at 15:30 UTC
    First of all:
    use strict; use warnings;
    This will save you a lot of time debugging.
    This is how I would go about traversing your hash:
    for my $key(keys %termservers) { for my $key2(keys %{$termservers{$key}}) { print "$key1 - $key2 = $termservers{$key1}{$key2}\n"; } }
    Update:
    If you don't already have it, and I'm guessing you don't, get the "Camel" book (Programming Perl). Chapter 9 discusses data structures in depth. This book is a must read for any perl programmer.
      Update:
      If you don't already have it, and I'm guessing you don't, get the "Camel" book (Programming Perl). Chapter 9 discusses data structures in depth. This book is a must read for any perl programmer.

      Though I would recommend the book, "perldoc perldsc" does a pretty good job as well, and then you don't have to wait to you can get a book (or get to a Camel book) to get the skinny on data structures.

      -enlil
        There's even a specific book on modules, references and objects, which I suspect is an edited and expanded version of the core documentation regarding those subjects. According to some reviews I've seen, it's pretty good.

        Arjen

Re: Hash of hashes question
by etcshadow (Priest) on Oct 22, 2003 at 15:31 UTC
    That last line:
    print "3", keys({%termservers{$­key}}), "\n"; #doesn't work#
    should be this:
    print "3", keys(%{$termservers{$­key}}), "\n"; #doesn't work#

    ------------
    :Wq
    Not an editor command: Wq
      To make the output a little more readable:
      print "3", join( ", ", keys(%{$termservers{$key}})), "\n"; #doesn't w +ork#
      Otherwise you just get the keys printed together and it's hard to tell where one stops and the next begins.
      You forgot to remove one of the two braces on the right :-)
      print "3", keys(%{$termservers{$­key}}), "\n"; should be this: print "3", keys(%{$termservers{$­key}), "\n";
        No. There are supposed to be two close-braces and one close-parenthesis. Let me spell it out:
        keys( # take the keys of a hash %{ # dereference a hashref $termservers{ # hash-table lookup $keys } # END hash-table lookup } # END hash dereference ) # END keys(

        ------------
        :Wq
        Not an editor command: Wq
Re: Hash of hashes question
by Beechbone (Friar) on Oct 22, 2003 at 21:30 UTC
    BTW, I found it helpful to also use a reference for the outermost hash when nesting hashs. That way you don't have to think about two syntaxes...
    my $termservers = { TERM192_168_0_1 => { CE_36xx101 => "PORT_2047", CE_36xx122 => "PORT_2060", CE_36xx124 => "PORT_2062" }, TERM192_168_0_2 => { CE_26xx103 => "PORT_2012", CE_26xx109 => "PORT_2014" } }; foreach my $key1 (keys %{ $termservers }) { foreach my $key2 (keys %{ $termservers->{$key1} }) { print $termservers->{$key1}{$key2}, "\n"; } }

    Search, Ask, Know
Re: Hash of hashes question
by Anonymous Monk on Oct 22, 2003 at 19:02 UTC
    Just my version:
    #!/usr/bin/perl use strict; use warnings; my %termservers = ( TERM192_168_0_1 => { CE_36xx101 => "PORT_2047", CE_36xx122 => "PORT_2060", CE_36xx124 => "PORT_2062" }, TERM192_168_0_2 => { CE_26xx103 => "PORT_2012", CE_26xx109 => "PORT_2014" } ); foreach my $key (keys %termservers) { foreach my $key2 (keys %{$termservers{$key}}) { print "$key => $key2 => $termservers{$key}{$key2}\n"; } }
Re: Hash of hashes question
by Roger (Parson) on Oct 23, 2003 at 02:39 UTC
    One comment: add use strict to your code.

    %termservers{$key} is wrong, should be written as $termservers{$key}.

    You could rewrite that line as follows:
    print "3", qq{@{[keys %{$termservers{$key}}]}}, "\n";
    Note that the part %{ $termservers{$key} } dereferences an anonymous hash. And the part print qq{@{[ ... ]}} prints the hash keys space separated.