in reply to setting hash keys by array

my @array = qw(red green brown); my %hash; my $ptr = \%hash; $ptr = $ptr->{$_} = {} for @array; $ptr = 1;

Makeshifts last the longest.

Replies are listed 'Best First'.
Re: Re: setting hash keys by array
by blssu (Pilgrim) on Sep 09, 2002 at 18:47 UTC

    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 ) }
      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!