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

Dear Monks,

I have an array with keys, like:
$k[0] = "a" ; $k[1] = "b"; $k[2] = "c" ;

The number of keys can vary. Now I would like to access the hash in a hash in a...., like:
$my_hash_ref->{$k[0]}->{$k[1]}->{$k[2]} ;
Uhh, how do I access this in a generic way ?

Thanks a lot in advance
Luca

Replies are listed 'Best First'.
Re: I have a hash in a hash in a .....
by Roy Johnson (Monsignor) on Feb 21, 2006 at 15:30 UTC
    Recursively walk a hash to get to an element
    use strict; use warnings; sub pointer_to_element { use List::Util 'reduce'; reduce(sub { \($$a->{$b}) }, \shift, @_); } my @k = qw(a b c); my $href = {}; ${pointer_to_element $href, @k} = 5; use Data::Dumper; print Dumper($href);

    Caution: Contents may have been coded under pressure.
Re: I have a hash in a hash in a .....
by ikegami (Patriarch) on Feb 21, 2006 at 15:29 UTC

    The read-only result is in $r after the following snippet executes:

    my $r = $my_hash_ref; $r = $r->{$_} foreach @k;

    The read-write result is in $$p after the following snippet executes:

    my $p = \$my_hash_ref; $p = \($$p->{$_}) foreach @k;

      Read-only result? I'm not sure what you mean by that, but if you assign to an element of $r, that affects $my_hash_ref. They're all references so they're pointing at the same data.

      #!/usr/bin/perl use Data::Dumper; my $hash = { a => { ab => { ac => 'fred' }, abb => 'barney' }, b => 'betty', c => { cb => 'dino' }, }; my $r = $hash; my @k = qw( a ab ); print Dumper( $hash ); $r = $r->{$_} foreach @k; $r->{ 'ac' } = 'Mr. Slate'; print Dumper( $hash );
      --
      brian d foy <brian@stonehenge.com>
      Subscribe to The Perl Review

        You didn't change $r the accessed value in your snippet — you changed that which is pointed by $r — so you failed to disprove that $r the accessed value is read-only.

        Say you want to do $my_hash_ref->{$k[0]}->{$k[1]}->{$k[2]} = 3;. Compare

        use Data::Dumper; my $my_hash_ref = { a => { b => { c => 2 } } }; my @k = qw( a b c ); my $r = $my_hash_ref; $r = $r->{$_} foreach @k; $r = 3; print Dumper($my_hash_ref); # { 'a' => { 'b' => { 'c' => 2 } } };

        with

        use Data::Dumper; my $my_hash_ref = { a => { b => { c => 2 } } }; my @k = qw( a b c ); my $p = \$my_hash_ref; $p = \($$p->{$_}) foreach @k; $$p = 3; print Dumper($my_hash_ref); # { 'a' => { 'b' => { 'c' => 3 } } };

        Update: Fixed a terminology error.