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

I am having trouble accessing a hash of unknown dimensions. I have an anonymous hash which looks like this :
$data{$a}{$b}{$c}{columns} = @ $data{$a}{$b}{$c}{values} = @ $data{$d}{$e}{columns} = @
As you can see from the structure I will always have columns and values key at the end which points to an array. I wrote a subroutine thanks to the help of the monks (see unknown number of dimensions of a multidimensional hash) to build this structure and now I am having problems accessing that data! Can you show me the way to go through the levels of the hash until I reach those keys and print or manipulate those arrays? Should i be storing those keys in an array and use those and if so how would I use them? Thanks in advance.

Replies are listed 'Best First'.
Re: Accesing hash of unknown dimension
by friedo (Prior) on Mar 20, 2006 at 22:16 UTC
    One way is a recursive function:

    sub trav_hash { my $ref = shift; my $type = ref $ref; if( $type eq 'HASH' ) { trav_hash( $ref->{$_} ) for keys %$ref; } elsif ( $type eq 'ARRAY' ) { handle_array( $ref ); } else { die "something weird is in our structure!"; } } sub handle_array { my $arrayref = shift; # do whatever we want with the array here.... } trav_hash( \%data );
      Thanks for the help, I need to read about references again. even the sub to create the structure can actually be used to access it if I store the keys in an array. I would be interested in seeing more solutions if they exist.
Re: Accesing hash of unknown dimension
by GrandFather (Saint) on Mar 20, 2006 at 22:40 UTC

    Do you want to iterate over the whole thing, or do you have the keys for the node you want to access? If the latter then the code I posted in reply to your question can be used to access the node given the "key path". Otherwise you need to specify your problem a little more accurately.

    The following code may help however:

    my %data; @{$data{a}{b}{c}{columns}} = [1, 2, 3]; @{$data{a}{b}{c}{values}} = [4, 5, 6]; @{$data{d}{e}{columns}} = [7, 8, 9]; my %leaves; walkHash (\%data); print "columns: "; print "@$_ " for @{$leaves{columns}}; print "\nvalues: "; print "@$_ " for @{$leaves{values}}; sub walkHash { my $subHash = shift; for (keys %$subHash) { if (/columns/) { push @{$leaves{columns}}, @{$subHash->{$_}}; } elsif (/values/) { push @{$leaves{values}}, @{$subHash->{$_}}; } else { walkHash ($subHash->{$_}); } } }

    Prints:

    columns: 1 2 3 7 8 9 values: 4 5 6

    DWIM is Perl's answer to Gödel
      Yes I realized that later on if you look at my reply to friedo, I should have looked at your answer again :).