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

Hello, I'm trying to implement a fairly involved data structure incorporating a hash of hashes, but I'm running into a LOT of difficulties, and I'm really stuck. I've written a demo program which exhibits the same problems. The following seems to run OK:
#!usr/bin/perl -w use strict; my @names = ("Tom", "Mary", "Nat", "Luke"); my %people; for(my $i=0; $i < @names; $i++) { $people{$names[$i]}={}; $people{$names[$i]}{number}=$i; $people{$names[$i]}{numbx2}=$i*2; } foreach my $key (keys(%people)) { print "\n".$key."\t".$people{$key}{numbx2}."\t".$people{$key}{number}; }
But Perl doesn't seem to like this at all:
#!usr/bin/perl -w use strict; my @names = ("Tom", "Mary", "Nat", "Luke"); my %people; for(my $i=0; $i < @names; $i++) { $people{$names[$i]}={}; $people{$names[$i]}{number}=$i; $people{$names[$i]}{numbx2}=$i*2; } foreach my $key (keys(%people)) { foreach my $pkey (keys($people{$key})) { print "\n".$key."\t".$people{$key}{$pkey}; } }
Also if I change the innermost foreach line to read

foreach my $pkey (keys(%people{$key})) {

(note the change from $ to %) -- which intuitively I would have thought was correct -- I also can't get the program to run.

I have read through the Perl documentation on a hash of hashes, but it's not terribly enlightening. After several infuriating hours I'm well and truly stuck -- any help is greatly appreciated.

Thanks very much.

Luke

Replies are listed 'Best First'.
Re: Hash of hashes problem
by moritz (Cardinal) on Oct 11, 2007 at 13:38 UTC
    The syntax you are looking for is keys %{$people{$key}}
      Thank you!! Without wishing to seem lazy, do you know where this is explained in the perl documentation? (I have looked.)
Re: Hash of hashes problem
by johngg (Canon) on Oct 11, 2007 at 14:32 UTC
    Here are a couple of pointers to save you some typing. Firstly, you can use the quotewords operator, qw{ ... }, when initialising your array of names.

    my @names = qw{ Tom Mary Nat Luke };

    It is more idiomatic to use a Perl-style loop rather than a C-style loop and also create your sub-hash in one go. (Note that $#array is the highest subscript whereas the array itself in scalar context, scalar @array, returns the number of elements).

    foreach my $idx ( 0 .. $#names ) { $people{$names[$idx]} = { number => $idx, numbx2 => $idx * 2, }; }

    Note that you can also iterate directly over the names if you so desire, though it's not applicable in the code you give.

    foreach my $name ( @names ) { $people{$name} = { this => q{that} }; }

    I hope this is useful.

    Cheers,

    JohnGG

Re: Hash of hashes problem
by ikegami (Patriarch) on Oct 11, 2007 at 14:02 UTC

    "But Perl doesn't seem to like this at all" and "I also can't get the program to run." are very poor descriptions. In the future, give error messages, etc

    You want the hash referenced by $people{$key}.
    Two steps.
    1. Start with the reference: $people{$key}.
    2. Then dereference it: %{ $people{$key} }.