Note that the original definitions of the hashes was wrong; use ()'s, not {}. The latter are for defining refs to anonymous hashes.
The solution below assumes that there is a 1-to-1 correspondence between ids and names; this seems problematic to me, since the two can easily get out of synch. I think that a better design would be to have only ids and scores in the input hash, and have a separate hash only for associating ids and names.
use strict; use warnings; use Dumpvalue; my %in_hash = ( jibber => [ {id => 1, score => 3, name => 'foo'}, {id => 5, score => 1, name => 'bar'}, {id => 22, score => 6, name => 'baz'}, ], jabber => [ {id => 3, score => 1, name => 'boo'}, {id => 5, score => 3, name => 'bar'}, {id => 12, score => 2, name => 'zib'}, {id => 22, score => 2, name => 'baz'}, ], ); Dumpvalue->new()->dumpValue( process( \%in_hash ) ); exit; sub process { my $input_hash = shift; my %indices; my %results; while ( my ( $key, $arr ) = each %$input_hash ) { for my $h ( @$arr ) { my $id = $h->{ id }; push @{ $indices{ $id } }, $key; $results{ $id }{ id } ||= $id; # redundant but convenient $results{ $id }{ name } ||= $h->{ name }; $results{ $id }{ score } += $h->{ score }; } } my %out; push @{ $out{ join ' ', @{ $indices{ $_ } } } }, $results{ $_ } for keys %indices; return \%out; } __END__ 'jabber' => ARRAY(0x8164664) 0 HASH(0x8164520) 'id' => 3 'name' => 'boo' 'score' => 1 1 HASH(0x816458c) 'id' => 12 'name' => 'zib' 'score' => 2 'jibber' => ARRAY(0x8164640) 0 HASH(0x8194ecc) 'id' => 1 'name' => 'foo' 'score' => 3 'jibber jabber' => ARRAY(0x816461c) 0 HASH(0x81644c0) 'id' => 22 'name' => 'baz' 'score' => 8 1 HASH(0x8194f44) 'id' => 5 'name' => 'bar' 'score' => 4
the lowliest monk
In reply to Re: combining hashes based on key values
by tlm
in thread combining hashes based on key values
by punkish
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |