Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Confused on handling merging values for hash of hashes

by shmem (Chancellor)
on Feb 04, 2015 at 21:21 UTC ( [id://1115572]=note: print w/replies, xml ) Need Help??


in reply to Confused on handling merging values for hash of hashes

Read perlref. Again. Play with the structures.

Your %HOH corrected:

%HOH = ( # not [ ! 1 => { # key => 1, person => "Mike", possession => "wallet, keys, car, house", age => 25, }, 2 => { # key => 2, person => "Mike", possession => "dog, cat, baseball bat", age => 25, }, 3 => { # key => 3, person => "Dave", possession => "pony, house, car, keys", age => 21, }, ); # not ] !

Likewise for your @AOH. Spot the error. Read perldata and perlref, again. Now to your ostensible problem:

How would one consolidate the hash of hashes to another hash of hashes or array of hashes so that if person and age were same, the possession would be a merge of the possession ... resulting in one entry per person/age combination but with all possessions in the array(list) of values for the possession key?
use Data::Dumper; use strict; use warnings; my %HOH = ( # not [ ! 1 => { # key => 1, person => "Mike", possession => "wallet, keys, car, house", age => 25, }, 2 => { # key => 2, person => "Mike", possession => "dog, cat, baseball bat", age => 25, }, 3 => { # key => 3, person => "Dave", possession => "pony, house, car, keys", age => 21, }, ); # not ] ! my %NewHOH; # consolidated hash. { # limit scope of %seen to this block my %seen; # intermediate hash. Key is "person:age" for my $key (keys %HOH) { # iterate over the keys of the hash my $val = $HOH{$key}; # get the value - an anonymous hash my $composite_key = join ":", $HOH{$key}->{person}, $HOH{$key}->{a +ge}; if ($seen{$composite_key}++) { # note: post increment! # we make the comma-separated string into an array. # then we build a hash using the array elements as keys. # this avoids duplicates. We later convert that back. my @possessions = split /,\s*/, $HOH{$key}->{possession}; for my $item (@possessions) { $NewHOH{$composite_key}->{possession}->{$item}++; } } else { # first occurence of this "person:age" key $NewHOH{$composite_key} = $HOH{$key}; # same as above. Make a hash of the items of "possession" $NewHOH{$composite_key}->{possession} = { map { $_, 1 } split /,\s*/, $HOH{$key}->{possession} }; + # record the first key, we'll use that to re-key the hash $NewHOH{$composite_key}->{key} = $key; } } } # now get rid of composite keys and make the anon arrays # of the "possession" value into a string for my $key ( keys %NewHOH ) { my $val = delete $NewHOH{$key}; # returns the anon hash my $new_key = delete $val->{key}; # old key which was remembered $NewHOH{$new_key} = $val; $val->{possession} = join ", ", keys %{$val->{possession}}; } # debug output $Data::Dumper::Indent = 1; my $d = Data::Dumper->new( [\%NewHOH], ['NewHOH'], ); print $d->Dump; __END__ $NewHOH = { '1' => { 'possession' => 'house, keys, baseball bat, cat, dog, car, wallet' +, 'person' => 'Mike', 'age' => 25 }, '3' => { 'possession' => 'keys, house, pony, car', 'person' => 'Dave', 'age' => 21 } };

Note that after __END__, the output shows an anonymous hash! See Data::Dumper, map and split. See perlref, perldata.

perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1115572]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-24 05:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found