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

I have a reference to a hash of hashs. e.g.
use vars qw($v); $v = ( h1 => { k1 => vh1k1, k2 => vh1k2, } h2 => { k1 => vh2k1, k2 => vh2k2, } )
Now I'd like to access the values for a sub hash in a foreach loop, but only for a given occurrence of 'h1' or 'h2'. e.g.
my $ofCurrentInterest = 'h1'; foreach $key (keys $v->{$ofCurrentInterest}) { $$key = $v->{ofCurrentInterst}->{$key} }
I've tried all the approaches I can think off but the compiler is never happy that I am passing a hash to keys.

Does anyone have any tips please?

Thanks

Replies are listed 'Best First'.
Re: using keys on hash of hash
by pjf (Curate) on May 22, 2008 at 02:08 UTC

    %{ expr } is your friend:

    my $v = { h1 => { k1 => 1, k2 => 2, }, h2 => { k1 => 3, k2 => 4, }, }; my $interest = 'h1'; foreach my $key ( keys %{ $v->{$interest} } ) { print "$key has value $v->{$interest}{$key}\n"; } __END__ k2 has value 2 k1 has value 1
Re: using keys on hash of hash
by ysth (Canon) on May 22, 2008 at 02:28 UTC
Re: using keys on hash of hash
by hesco (Deacon) on May 22, 2008 at 02:39 UTC
    What pjf is saying to you is this:

    keys operates on hashes, not on hash references. By dereferencing the reference, you turn it back into a hash and keys then knows what to do with it. Your issue is not that you are handling a hash_of_hashes, but that you are dealing with a reference to a h_o_h.

    -- Hugh

    if( $lal && $lol ) { $life++; }
Re: using keys on hash of hash
by Herkum (Parson) on May 22, 2008 at 04:40 UTC
    How about using an approach that makes it easier to understand your logic.
    use Data::Dumper qw(Dumper); my %hash = ( 'h1' => { 'k1' => 'vh1k1', 'k2' => 'vh1k2', }, 'h2' => { 'k1' => 'vh2k1', 'k2' => 'vh2k2', } ); my $key = 'h1'; my $results = find_results_for( $key ); if ($results) { print "Results for $key: " . Dumper( $results ) . "\n"; } else { print "Cannot find anything for $key\n"; } sub find_results_for { my $search_key = shift; return if not exists $hash{$search_key}; return $hash{$search_key}; }

    Avoid using nested loops without a very good reason. They can be hard to follow, better to put then in a subroutine that can explain what you looking for.

Re: using keys on hash of hash
by moritz (Cardinal) on May 22, 2008 at 08:43 UTC
    Although it has been corrected, I think nobody so far told you that you made two syntax errors. The first is to use parenthesis instead of curly brackets. This constructs a list, not a hash reference. In scalar context that yields the last item of the list, which is the second half of your hash.

    Note that the "fat arrows" => do not influence the type of the thing you are constructing, it's merely a weird looking comma that automagically quotes the thing on its LHS. So you could even write things like this:

    my @list = foo => bar => 'baz';

    The second error (this time a real syntax error that perl chokes on) is that you are missing a comma before h2.

Re: using keys on hash of hash
by Anonymous Monk on May 22, 2008 at 02:35 UTC

    When you use the %{...} construction as-noted, you basically are telling the compiler to shut-up: that you know what you are doing; that you know what kind of value the value will be. This declaration will silence the error, but it's up to you to make sure that what you promise is always actually so.