in reply to Re: setting hash keys by array
in thread setting hash keys by array

That code (and several other examples) don't work quite like the request:

$hash{red}{green}{brown} = 1

They do this instead:

$hash{red}{green}{brown} = { }

That inner-most key makes a lot of the foreach solutions kind of ugly because the last key must be treated specially -- unless there's a way to transmogrify a hash ref into a scalar ref? Here's a short reverse foreach that uses globs to solve the corner case:

my @array = qw(red green brown); use vars qw(%hash); foreach (reverse @array) { *hash = { $_ => (%hash) ? \%hash : 1 } }

The lexical version is more ugly and a lot less efficient:

my @array = qw(red green brown); my %hash; foreach (reverse @array) { %hash = ( $_ => (%hash) ? { %hash } : 1 ) }

Replies are listed 'Best First'.
Re^3: setting hash keys by array
by Aristotle (Chancellor) on Sep 09, 2002 at 19:22 UTC
    They do this instead: $hash{red}{green}{brown} = { }
    True, that's what comes out of the for loop. Then the next instruction in my sample turns it into the requested result.. Is the following more to your liking?
    my $ptr = \%hash; $ptr = $ptr->{$_} = {} for @array[0..$#array-1]; # fixed; s/shift @arr +ay/$_/ $ptr->{$array[-1]} = 1;
    or maybe
    my $ptr = \%hash; $ptr = $ptr->{shift @array} = {} while @array > 1; $ptr->{$array[0]} = 1;
    Update: forgot to remove the shift when I initially copypasted. See comment.

    Makeshifts last the longest.

      Did your $ptr = 1 line really work on your machine? It didn't on mine.

      At least your new code is correct... ;) BTW, if you use the -1 index on array, you don't need to shift @array in the loop -- that's the version I'd prefer in production code.

      Anyways, it was just fun looking at alternatives. It's not often I see a clean use of type globs!

        Oops. I wrote the while version first and forgot to change the shift into a plain $_ when I copypasted. Fixed.

        Makeshifts last the longest.