How do I append hash a to hash b in Perl without using a loop?
Asked
Active
Viewed 2.7k times
13
-
4Why don't you want to use a loop? – brian d foy Aug 08 '09 at 01:12
4 Answers
32
If you mean take the union of their data, just do:
%c = (%a, %b);

bdonlan
- 224,562
- 31
- 268
- 324
-
3It works for me: "%a=('a' => 'b', 'c' => 1); %b=('c' => 'd'); %a = (%a, %b); print join(', ', map { "'$_' => \"${a{$_}}\"" } keys %a), "\n";" Items from %b with the same key take precedence, but other items from %a are present after the union. – outis Aug 06 '09 at 23:51
-
that might be the OP's problem, they might want to merge the values of the hash, so $a{'c'} ends up being [1, 'd'] – MkV Aug 07 '09 at 10:51
-
5
24
You can also use slices to merge one hash into another:
@a{keys %b} = values %b;
Note that items in %b will overwrite items in %a that have the same key.

outis
- 75,655
- 22
- 151
- 221
-
5For extra credit, with a hash ref in a and b, we do @{$a}{keys %$b} = values %$b; – daotoad Aug 07 '09 at 05:30
-
2I expect this to be more efficient than the other reply, because that one recreates the hash also for the already existing items, while this one just adds keys for the new items. If there were many items in %a, compared to %b, the difference can be respectable. – bart Aug 10 '09 at 20:04
-
1Maybe. My approach also walks %b twice. If %b is larger than %a, the other technique might be faster. Fastest of all might be a loop, but the OP didn't want that. – outis Aug 10 '09 at 20:49
-
1@bart: looks like you were right. Some rather simple timing tests for perl 5.8.9 on OS X 10.4 place the slice approach about 2.4 times faster, even with %b much larger than %a. Your mileage may vary. – outis Aug 10 '09 at 21:01
-
1This should also work for blessed hashrefs if I'm not severely mistaken. Trying it out now. Handy! – onitake Sep 25 '13 at 18:25
2
This will merge hashes and also take into account undefined entries, so they don't replace the content.
my %hash = merge(\%hash1, \%hash2, \%hash3);
sub merge {
my %result;
%result = %{ $_[0] };
shift;
foreach my $ref (@_) {
for my $key ( keys %{$ref} ) {
if ( defined $ref->{$key} ) {
$result{$key} = $ref->{$key};
}
}
}
return %result;
}

Michael
- 21
- 1