use strict; use warnings; use Data::Dumper; my %first = ( one => 1, two => 2, three => 3 ); my %second = ( one => 'uno', two => 'dos', foo => 'bar' ); my %third = ( one => [ 'this', 'is', 'a', 'test' ], two => 'dos', foo => { bar => 'raise', baz => 'test' } ); my %new_hash = merge( \%first, \%second, \%third ); print Dumper( \%new_hash ); sub merge { my @hashes = @_; my ( %merged_hash, %temp, @keys ); # grab unique keys foreach my $hash ( @hashes ) { foreach my $key ( keys %$hash ) { push @keys, $key if ! $temp{ $key }++; } } my @vals; # build the array foreach my $key ( @keys ) { foreach my $hash ( @hashes ) { push @vals, $hash->{ $key } if exists $hash->{ $key }; } $merged_hash{ $key } = [@vals]; @vals = (); } return %merged_hash; } #### $VAR1 = { 'one' => [ 1, 'uno', [ 'this', 'is', 'a', 'test' ] ], 'three' => [ 3 ], 'foo' => [ 'bar', { 'baz' => 'test', 'bar' => 'raise' } ], 'two' => [ 2, 'dos', 'dos' ] };