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

Hi folks I am passing a list containing a variable number of items to a function. This list represents a path in a tree-like data structure made up of hashes to hashes to hashes etc. The items represent the hash keys. The problem I'm having is accessing this tree node when the list contains a unpredictable number of items. for example if we always had 3 items we could simply do a
$HOH{item1}{item2}{item3}="value";
I need to find a way to do something like
@list=(item1 item2 item3 .. itemx) $HOH{item1}{item2}{item3}..{itemx}="value"
I've written a recursive function that walks the data structure using the passed list but this seems like over kill I know exactly where I want to go and should be able to jump straight there. Any ideas ?

Replies are listed 'Best First'.
Re: Hash to Hash to Hash ....
by Hofmator (Curate) on Aug 20, 2001 at 17:35 UTC

    There is a straight forward iterative solution:

    my @list1 = qw/item1 item2 item3/; my @list2 = qw/item1 item2 item4 item5/; my %hash; my $hr = \%hash; $hash{item1}{item2}{item3} = 3; $hash{item1}{item2}{item4}{item5} = 4; $hr = $hr->{$_} for (@list1); print $hr; $hr = \%hash; $hr = $hr->{$_} for (@list2); print $hr;

    -- Hofmator

Re: Hash to Hash to Hash ....
by ariels (Curate) on Aug 20, 2001 at 17:51 UTC
    You'll have to go over all the keys in your list. You don't need to recurse if you don't want to, though:
    # traverse($hoh, @key): return value of $hoh->{$key[0]}...{$key[-1]} sub traverse { my $hoh = shift; $hoh = $hoh->{$_} for (@_); $hoh } # set($hoh,$val, @path): ... sub set { my $hoh = shift; my $val = shift; my $last = pop @_; $hoh = $hoh->{$_} for (@_); $hoh->{$last} = $val }
    Note, however, that the set sub does not do auto vivification of hash keys for you. This might be regarded a feature, but probably isn't.
      Hi Me here again. Can't find the ref to 'auto vivification'. Still trying to find out more about it. Can you give me a brief run down.

      I been using the set() function which works well. The next step is to add items into the tree. To do this I am using the same idea of passing a path. The question arises when passing a new path to a empty tree. i.e
      set($ref_to_hash,1,(a c b d)) # set($hoh,$val, @path): ... by ariels sub set { my $hoh = shift; my $val = shift; my $last = pop @_; $hoh = $hoh->{$_} for (@_); $hoh->{$last} = $val }
      the set function works if the 'a c b ' already exists. If it doesn't then we simply create a hash in space somewhere ( i think ). What I need is to dynamically create nodes which do no exist. I have done this by using a temporary hash to add the new item in and then link it back into the tree.
      #create first node $hr=\%I; $hr->{'one'}=1; #create tmp node and link back in $new=\%tmp; $new->{'two'}=1; $hr->{'one'}=$new;
      Seems to work ok but I reckon you'll have a better way Thanks again wert
        just found out about auto autovivification. Seems to all tie together. The book says 'This is what happens when you try to assign through an undefined references and Perl automatically creates the reference you're trying to use.'
Re: Hash to Hash to Hash ....
by wertert (Sexton) on Aug 20, 2001 at 18:11 UTC
    Thanks alot guys. It works a treat. wert