如何在 Perl 中组合散列?

将两个散列组合成% hash1的最佳方法是什么?我总是知道% hash2和% hash1总是有唯一的键。如果可能的话,我也希望使用一行代码。

$hash1{'1'} = 'red';
$hash1{'2'} = 'blue';
$hash2{'3'} = 'green';
$hash2{'4'} = 'yellow';
108745 次浏览

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

See also


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;

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

For hash references. You should use curly braces like the following:

$hash_ref1 = {%$hash_ref1, %$hash_ref2};

and not the suggested answer above using parenthesis:

$hash_ref1 = ($hash_ref1, $hash_ref2);