Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

unknown number of dimensions of a multidimensional hash

by Otogi (Beadle)
on Mar 09, 2006 at 23:10 UTC ( #535551=perlquestion: print w/replies, xml ) Need Help??

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

This most probably has been answered before but can't come up with the right keys to research it. I want to dynamically create a hash with multiple dimensions (number of dimensions dynamically increase) for example:
$data {$a}{$b} $data {$a}{$b}{$c} $data {$d}{$e}
So as the script is running I could add more dimensions to the initial hash using a subroutine called given the initial  $data{$a} . How do I do that? and how would I read the hash to get the keys and values if I don't know the dimension of the hash. Thank you.

Replies are listed 'Best First'.
Re: unknown number of dimensions of a multidimensional hash
by GrandFather (Sage) on Mar 09, 2006 at 23:22 UTC

    The following code is taken from a game engine and manipulates "keys" of the form (\w+\.)+\w+. Each word represents a hash level.

    our %GameState; # The entire game context # looks up a key (passed as the first param) and adds the value # (if provided as second param). Returns a reference to the value # list. sub Entity { my ($key, $value) = @_; return undef if ! defined $key; my $hash = \%GameGlobals::GameState; my @keys = split /\./, $key; map {$_ = lc $_} @keys; while (@keys && defined $hash) { my $key = shift @keys; if (@keys) { $hash->{$key} = {} if ! exists $hash->{$key}; $hash = $hash->{$key}; } else { $hash->{$key} = [] if ! exists $hash->{$key}; push @{$hash->{$key}}, $_[1] if defined $value; return \$hash->{$key}; } } }

    DWIM is Perl's answer to Gödel
Re: unknown number of dimensions of a multidimensional hash
by duff (Parson) on Mar 10, 2006 at 00:47 UTC

    Another thing you can do is use concatenated keys rather than a multidimensional data structure. (I don't know how critical the hierarchical nature is to your problem solution) That is, instead of:

    $data {$a}{$b} $data {$a}{$b}{$c} $data {$d}{$e}
    you would use
    $data{join "\0", $a, $b} $data{join "\0", $a, $b, $c} $data{join "\0", $d, $e}
    Then to access the keys you'd use your standard keys operator:
    for (keys %data) { # you could do something with $data{$_} directly, # or if you need access to the individual keys ... my @keys = split /\0/; # ... }
    The main caveat is that your "key separator" should be something that doesn't appear in your keys. I chose "\0" in this example assuming that your keys aren't likely to contain NUL bytes.
Re: unknown number of dimensions of a multidimensional hash
by Anonymous Monk on Mar 10, 2006 at 00:47 UTC

    If the hash is not ragged, you simply know its dimensionality. If you somehow lose this information

    sub hashfirst { $_[0]->{($_) = keys %{$_[0]}} } sub shape { my $h = shift; my @s; for (;'HASH' ne ref $h; $h = hashfirst($h)) { push @s, scalar(keys %$h); } @s }

    may help you remember. This feels like an X-Y question.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://535551]
Approved by GrandFather
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (2)
As of 2020-10-25 02:30 GMT
Find Nodes?
    Voting Booth?
    My favourite web site is:

    Results (248 votes). Check out past polls.