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

I want a hash of hashes. That's not a new thing. I want to build it by using a stack of indexes. I've never seen that before. I'd work something like this, but less stupid looking:
sub builder() {
    ($data, $i) = @_;
    $hash{$i[0]}               = $data if @{ $i } == 1;
    $hash{$i[0]}{$i[1]}        = $data if @{ $i } == 2;
    $hash{$i[0]}{$i[1]}{$i[2]} = $data if @{ $i } == 3;
}

Replies are listed 'Best First'.
RE: Nesting... or something.
by Fastolfe (Vicar) on Jun 03, 2000 at 19:56 UTC
    Why not do something like this:
    # Note: Don't prototype () since that won't let you pass args sub builder { my $data = shift; # $i in your code I'm keep +ing in @_ my %hash = (); my $ptr = \%hash; # Set up a pointer to %has +h for (my $cur = 0; $cur < $#_; $cur++) { $ptr->{$_[$cur]} = {}; # Manipulate using our poi +nter $ptr = $ptr->{$_[$cur]}; # and advance it as we go } $ptr->{$_[$#_]} = $data; # Do our last hash return %hash; # and do what you want wit +h %hash } my %hash = builder('abcde', 'a', 'b', 3); print $hash{'a'}{'b'}{3}; # 'abcde'
    I used @_ instead of your $i reference, but change things around if you really need it that way. The idea's the same. Perhaps there's a more elegant solution but I couldn't see one at the moment. Have fun.
      This is almost what I wanted. I wanted the builder sub to actually build on the hash though. This seems to replace it. Each successive call to the builder should add to the contents of the hash. BTW, I was the original poster, but my cookies were foob'd.
        what you want is not possible, because you can't have a single hash key retrieve both a plain scalar and a hash reference.
        my %hash; $hash{foo} = 'bar'; # the following replaces the value of $hash{foo} with a hash reference $hash{foo}{bar} = 'baz'; # the following is equivalent $hash{foo} = { bar => 'baz' };
        so, if someone did: builder('baz', [ 'foo', 'bar' ]); it would wipe out the effect of: builder('bar', [ 'foo' ]);
        Pass the hash as a reference instead of using %hash, and on the line where it assigns the $ptr->{$key} = {} add something like "unless ref($ptr->{$key}) eq 'HASH'" or something.. that will probably wipe out any existing values you put in there though.. e.g.:
        builder(\%test, 'abc', 1, 2); # $test{1}{2} = 'abc' builder(\%test, 'def', 1, 2, 3); # $test{1}{2} is now a hashref, not +'abc'
Re: Nesting... or something.
by Maqs (Deacon) on Jun 03, 2000 at 20:19 UTC