perlperl-data-structures

Perl: How to turn array into nested hash keys


I need to convert a flat list of keys into a nested hash, as follow:

my $hash = {};

my @array = qw(key1 key2 lastKey Value);

ToNestedHash($hash, @array);

Would do this:

$hash{'key1'}{'key2'}{'lastKey'} = "Value";


Solution

  • sub to_nested_hash {
        my $ref   = \shift;  
        my $h     = $$ref;
        my $value = pop;
        $ref      = \$$ref->{ $_ } foreach @_;
        $$ref     = $value;
        return $h;
    }
    

    Explanation:

    We know:

    It might be more explicit to do this:

    foreach my $key ( @_ ) { 
        my $lvl = $$ref = {};
        $ref    = \$lvl->{ $key };
    }
    

    But owing to repeated use of these reference idioms, I wrote that line totally as it was and tested it before posting, without error.

    As for alternatives, the following version is "easier" (to think up)

    sub to_nested_hash {
        $_[0] //= {};
        my $h     = shift;
        my $value = pop;
        eval '$h'.(join '', map "->{\$_[$i]}", 0..$#_).' = $value';
        return $h;
    }
    

    But about 6-7 times slower.