Create a multidimesional key of hash from array?

First, use pop to separate the value to assign from the keys. Then, you can use either of the following:

use Data::Diver qw( DiveVal );

my %hash;
DiveVal(\%hash, map \$_, @keys) = $val;

or

sub dive_val :lvalue {
   my $p = \shift;
   $p = \( $$p->{$_} ) for @_;
   $$p
}

my %hash;
dive_val(\%hash, @keys) = $val;

dive_val works by having $p reference the next value to dereference and/or modify.

Pre-loop:            $p references $hash (the anon scalar referencing %hash)
After loop pass 0:   $p references $hash->{1}
After loop pass 1:   $p references $hash->{1}{2}
After loop pass 2:   $p references $hash->{1}{2}{3}
After loop pass 3:   $p references $hash->{1}{2}{3}{4}

The extra level of indirection has many benefits.

  • It removes the need to treat the last key specially.
  • It removes the need to create the hash before it’s dereferenced.
  • It removes the need for the root to be a reference to a hash. Instead, any scalar can be the root, even an undefined one.
  • It makes it easy to extend dive_val to support mixed array/hash structures.

Leave a Comment