How can I combine hashes in Perl?
This is an old question, but comes out high in my Google search for 'perl merge hashes' - and yet it does not mention the very helpful CPAN module Hash::Merge
Quick Answer (TL;DR)
%hash1 = (%hash1, %hash2) ## or else ... @hash1{keys %hash2} = values %hash2; ## or with references ... $hash_ref1 = { %$hash_ref1, %$hash_ref2 };
Overview
- Context: Perl 5.x
- Problem: The user wishes to merge two hashes1 into a single variable
Solution
- use the syntax above for simple variables
- use Hash::Merge for complex nested variables
Pitfalls
- What do to when both hashes contain one or more duplicate keys
- (see e.g., Perl - Merge hash containing duplicate keys)
- (see e.g., Perl hashes: how to deal with duplicate keys and get possible pair)
- Should a key-value pair with an empty value ever overwrite a key-value pair with a non-empty value?
- What constitutes an empty vs non-empty value in the first place? (e.g.
undef
, zero, empty string,false
, falsy ...)
- What constitutes an empty vs non-empty value in the first place? (e.g.
See also
- PM post on merging hashes
- PM Categorical Q&A hash union
- Perl Cookbook 5.10. Merging Hashes
- websearch://perlfaq "merge two hashes"
- websearch://perl merge hash
- https://metacpan.org/pod/Hash::Merge
Footnotes
1 * (aka associative-array, aka dictionary)
Check out perlfaq4: How do I merge two hashes. There is a lot of good information already in the Perl documentation and you can have it right away rather than waiting for someone else to answer it. :)
Before you decide to merge two hashes, you have to decide what to do if both hashes contain keys that are the same and if you want to leave the original hashes as they were.
If you want to preserve the original hashes, copy one hash (%hash1) to a new hash (%new_hash), then add the keys from the other hash (%hash2 to the new hash. Checking that the key already exists in %new_hash gives you a chance to decide what to do with the duplicates:
my %new_hash = %hash1; # make a copy; leave %hash1 alone
foreach my $key2 ( keys %hash2 )
{
if( exists $new_hash{$key2} )
{
warn "Key [$key2] is in both hashes!";
# handle the duplicate (perhaps only warning)
...
next;
}
else
{
$new_hash{$key2} = $hash2{$key2};
}
}
If you don't want to create a new hash, you can still use this looping technique; just change the %new_hash to %hash1.
foreach my $key2 ( keys %hash2 )
{
if( exists $hash1{$key2} )
{
warn "Key [$key2] is in both hashes!";
# handle the duplicate (perhaps only warning)
...
next;
}
else
{
$hash1{$key2} = $hash2{$key2};
}
}
If you don't care that one hash overwrites keys and values from the other, you could just use a hash slice to add one hash to another. In this case, values from %hash2 replace values from %hash1 when they have keys in common:
@hash1{ keys %hash2 } = values %hash2;