how to merge 2 deep hashes in perl
I write a sub in Perl to merge 2 hashes of the same structure; so that merge($a,$b)
$a = {
k1 => { sk1 => 'v1' },
k2 => { sk3 => 'v3', sk4 => 'v4' }
};
$b = {
k1 => { sk2 => 'v2'},
k3 => { sk5 => 'v5'}
};
would result in
$c = {
k1 => { sk1 => 'v1', sk2 => 'v2' },
k2 => { sk3 => 'v3', sk4 => 'v4' }
k3 => { sk5 => 'v5'}
};
Below is my code for merge,开发者_如何学JAVA and it does not work. How can I correct it? Thank you.
sub merge {
my ($old,$new) = @_;
foreach my $k (keys($old)) {
if (exists $new->{$k}) {
if (ref($old->{$k}) eq 'HASH') {
merge($old->{$k},$new->{$k});
} else {
$new->{$k} = $old->{$k};
}
} else {
$new->{$k} = $old->{$k};
}
}
return $new;
}
Unless you're doing this just to learn how it's done, I'd use a premade solution like Hash::Merge or Hash::Merge::Simple.
This should be plenty good enough:
for my $href ($a, $b) {
while (my($k,$v) = each %$href) {
$c->{$k} = $v;
}
}
If you don't want to clobber duplicates, perhaps because you're concerned about ordering issues, instead use:
for my $href ($a, $b) {
while (my($k,$v) = each %$href) {
push @{ $c->{$k} }, $v;
}
}
The advantage of doing this very simple operation yourself is it helps develop facility with basic Perl data structures, something critical on the path to fluency in the language.
Note however that these are surface copies, so references will be shared. It's not a deep copy.
I used each
instead of keys
so that it scales in case you use DBM hashes with millions of elements.
精彩评论