views:

119

answers:

2

I've just started diving in to the crazy world that is perl and have come across a problem that I cannot seem to wrap my head around. Specifically I need to be able to convert from one hash structure to another, that uses the keys/values as the new hashes keys/values.

An example:

Input hash:

    my %original_hash = (
    first_key => {  some_key => "apples",
                    another_key => "chips",
                    #potentially more here
                 },
     second_key => {  more_of_same => "dogs", 
                      its_another => "cats",
                      #potentially more here 
                   }
      );

Output hash:

my %final_hash = ( 
   some_key => { 
                    apples => { 
                                more_of_same => "dogs", 
                                its_another => "cats", 
                              } 
               } ,
   another_key => { 
                    chips => { 
                                more_of_same => "dogs", 
                                its_another => "cats",
                              } 
                  } 

);

And yes I do want the second_key's data repeated in the final_hash, as there will be an array of the original_hashes that are inputted. The first element becomes the base-case, and all other elements may append or remove from that list.

If anyone has any suggestions on how to go about doing this that would be greatly appreciated!

+2  A: 

Okay, Sinan is right, it's very hard to guess your problem, but the following code seems to do what you want ... or at least it produces the listed output.... :)

use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Deepcopy = 1;

my %original_hash = (
    first_key => {  some_key => "apples",
                    another_key => "chips",
                    #potentially more here
             },
 second_key => {  more_of_same => "dogs",
                  its_another => "cats",
                  #potentially more here
               }
);


my %final_hash;

for my $key ( keys %{ $original_hash{first_key} } ) {
        $final_hash{$key} = { 
           $original_hash{first_key}->{$key} 
                 => $original_hash{second_key}
           };
}


print Dumper(\%final_hash);
mdom
I do believe this is what I'm looking for :)I wanted to keep things generic instead of being spoon fed an exact answer. I should be able to apply it to my specific case (and hopefully learn more from it!)Thanks a ton!
Zack
+2  A: 

Here is another way

my %final_hash;

my %tmp = %{$original_hash{first_key}}; 
my $val = $original_hash{second_key};

while ( my ($k,$v) = each %tmp) {
    $final_hash{$k} =  { $v => $val };
}


print Dumper (\%final_hash);
ccheneson
Oh. Interesting. What are the advantages to doing it this way with the inclusion of the each function?
Zack
In terms of performance, I dont know, probably negligible.And Perl motto is TIMTOWTDI :) http://en.wikipedia.org/wiki/There's_more_than_one_way_to_do_it
ccheneson
Why `reverse`? Just switch places `$k` and `$v` inside the loop.
codeholic
@codeholic - well spoted
ccheneson
It might also be worth noting that the line: $final_hash{$k} = { $v => $val }; Only creates a shallow copy of val. In my particular case this was not good. To correct this: $final_hash{$k} = { $v => {%val} };
Zack