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'