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

1)I create a new hash from the original tree with just the nested keys using the hash_maker function.
2)I then want to populate the new hash with the original values ... (Original Values)

$VAR1 = [ { 'nodeType' => 'node', 'value' => '1', 'text' => 'int', 'children' => [ { 'nodeType' => 'node', 'value' => '1', 'text' => 'num', 'id' => 'int-num', 'leaf' => 'true' } ], 'id' => 'int', 'leaf' => 'false' }, { 'nodeType' => 'node', 'value' => '10.2.200.21', 'text' => 'device', 'children' => [ { 'nodeType' => 'node', 'value' => 'image1', 'text' => 'ftp_image_name', 'id' => 'device-ftp_image_name', 'leaf' => 'true' }, { 'nodeType' => 'node', 'value' => '6.1', 'text' => 'ftp_image_version', 'id' => 'device-ftp_image_version', 'leaf' => 'true' }, { 'nodeType' => 'node', 'value' => 'build/', 'text' => 'ftp_image_path', 'id' => 'device-ftp_image_path', 'leaf' => 'true' }, { 'nodeType' => 'node', 'value' => '10.2.200.21', 'text' => 'ftp_server', 'id' => 'device-ftp_server', 'leaf' => 'true' } ], 'id' => 'device', 'leaf' => 'false' }
1)(Created nested hash)
$VAR1 = { 'int' => { 'num' => {} }, 'device' => { 'ftp_image_path' => {}, 'ftp_image_version' => {}, 'ftp_image_name' => {}, 'ftp_server' => {} } };
2)Problem is after hash_maker function...how do I set the values for the new hash?

sub _process_attributes{ my $self = shift; my $child_tree = shift; my $attributes = shift || {}; my $attribute_values; foreach my $child (@$child_tree){ my $attribute_key = $child->{id}; my @attribute_array = split('-',$attribute_key); my $key; my $current_key; my $next_key; $attributes = hash_maker($attributes,@attribute_array); #2 MY PROBLEM IS HERE I WANT TO SET THE VALUES THAT MATCH THE KEYS BAS +ED ON THE NEWLY BUILD HASH #if($child->{leaf}){ # #} if($child->{children}){ $self->_process_attributes($child->{children},$attribute +s) } } return $attributes; } sub hash_maker { my $ref = shift; my $key = shift; return undef unless ref $ref eq 'HASH'; # # If $key is empty, we're building an empty hash. Return undef. # return undef unless $key; # # This is the passed in hash, so we need to duplicate it in our new # data structure. We also have to be sure that we're adding if neces +sary. # if ( ref $key eq 'HASH' ) { my $hash; my $count = keys %$key; my $cnt = 1; foreach my $k ( keys %{$key} ) { $ref->{$k} = $key->{$k}; } return $ref; } # # Reference was not a hashref, we don't know how to handle it. # return undef if ref $key; # # Nothing above was met, there's more to build. # $ref->{$key} = {} unless exists $ref->{$key}; #shift(@_); hash_maker( $ref->{$key}, @_ ); # # Pass that which we hath groweth to those who groweth before us... # return $ref; }

Replies are listed 'Best First'.
Re: Setting nested hash values recursively
by josh803316 (Beadle) on Nov 06, 2009 at 04:51 UTC
    I was able to solve my problem by doing the following. I'm sure there is a much more elegant solution and I would love to see it....but if anyone else is facing something like this hopefully it helps:
    #********************************************************************* +************** # protected _process_attributes # ***************************** # Uses: Recursively searches through a tree structure to process/f +ind attributes # Params: HASH with device and interface attributes # Return: The updated command and result set after template process +ing #********************************************************************* +************** sub _process_attributes{ my $self = shift; my $child_tree = shift; my $attributes = shift || {}; my $attribute_values; foreach my $child (@$child_tree){ my $attribute_key = $child->{id}; my @attribute_array = split('-',$attribute_key); my $key; my $current_key; my $next_key; $attributes = hash_maker($attributes,@attribute_array); if($child->{children}){ $self->_process_attributes($child->{children},$attributes) } if($child->{leaf}){ nested_keys($attributes,\@attribute_array,$child->{value}) +; } } return $attributes; } sub nested_keys{ my $attributes = shift; my $attribute_array = shift; my $value = shift; foreach my $attr (@$attribute_array){ foreach my $k (keys %$attributes){ unless($k eq $attr){ next; } my $num_keys = keys %{$attributes->{$k}}; if(ref($attributes->{$k}) eq 'HASH' && $num_keys > 0){ shift(@$attribute_array); nested_keys($attributes->{$k},\@$attribute_array,$valu +e); } else { $attributes->{$k} = $value; return; } } } } sub hash_maker { my $ref = shift; my $key = shift; return undef unless ref $ref eq 'HASH'; # # If $key is empty, we're building an empty hash. Return undef. # return undef unless $key; # # This is the passed in hash, so we need to duplicate it in our new # data structure. We also have to be sure that we're adding if neces +sary. # if ( ref $key eq 'HASH' ) { my $hash; my $count = keys %$key; my $cnt = 1; foreach my $k ( keys %{$key} ) { $ref->{$k} = $key->{$k}; } return $ref; } # # Reference was not a hashref, we don't know how to handle it. # return undef if ref $key; # # Nothing above was met, there's more to build. # $ref->{$key} = {} unless exists $ref->{$key}; #shift(@_); hash_maker( $ref->{$key}, @_ ); # # Pass that which we hath groweth to those who groweth before us... # return $ref; }