perl:与每个元素阵列合并深度合并

问题描述:

我想合并两个哈希,并且Hash::Merge几乎正是我所需要的,除了数组。我不需要连接数组,而是需要它执行每个元素的合并。perl:与每个元素阵列合并深度合并

例如:

use Hash::Merge qw (merge); 

my %a = ('arr' => [ { 'a' => 'b' } ]); 
my %b = ('arr' => [ { 'c' => 'd' } ]); 

my %c = %{ merge(\%a, \%b) }; 

期望的结果是('arr'=>[{'a'=>'b','c'=>'d'}]),实际结果是('arr'=>[{'a'=>'b'},{'c'=>'d'}])

这可以通过使用specify_behavior完成或者是有一些其他的方式?

+0

我不认为有''specify_behavior'方法,但我不熟悉这个模块。我相信它通过将2个散列引用数组合并成1个散列引用数组来执行期望的行为。我认为要深度合并,你必须编写更多的代码。但是,我真的不知道这个模块。注意:你需要一个带有1个元素的数组(一个散列引用),你可能会更好地使用带有深元素的散列引用。只是一个观察。 –

我认为specify_behaviour是用来指定如何处理冲突或不平衡的结构进行合并。这些文档实际上并不多说。但尝试一下,通过定义的快捷方式,或尝试自己设置它们。为您的数据结构,你可以尝试

SCALAR => ARRAY => sub { [ %{$_0}, %{$_[0]} ] } 
SCALAR => ARRAY => HASH => sub { [ $_[0], $_[0] ] } 

如果你尝试,并没有工作,你可能已经发现的模块中的错误?通过你所展示的,它并没有足够“深入”。这里没有模块。我扩大了你的样本结构。

use warnings; 
use strict; 

my %a = ( 
    'arr1' => [ { a => 'A', a1 => 'A1' } ], 
    'arr2' => [ { aa => 'AA', aa1 => 'AA1' } ] 
); 
my %b = ( 
    'arr1' => [ { b => 'B', b1 => 'B1' } ], 
    'arr2' => [ { bb => 'BB', bb1 => 'BB1' } ] 
); 
# Copy top level, %a to our target %c 
my %c; 
@c{keys %a} = values %a; 
# Iterate over hash keys, then through array 
foreach my $key (sort keys %c) { 
    my $arr_len = @{$c{$key}}; 
    foreach my $i (0..$arr_len-1) { 
     my %hb = %{ ${$b{$key}}[$i] }; 
     # merge: add %b to %c 
     @{ ${$c{$key}}[$i] }{keys %hb} = values %hb; 
    } 
} 
# Print it out 
foreach my $key (sort keys %c) { 
    print "$key: "; 
    my $arr_len = @{$c{$key}}; 
    foreach my $i (0..$arr_len-1) { 
     my %hc = %{ ${$c{$key}}[$i] }; 
     print "$_ => $hc{$_}, " for sort keys %hc; 
    } 
    print "\n"; 
} 

这将打印的%c内容(对准手动这里)

 

    arr1: a => A, a1 => A1, b => B, b1 => B1, 
    arr2: aa => AA, aa1 => AA1, bb => BB, bb1 => BB1, 

代码不处理的阵列/不相等的大小,但检查的哈希可以容易地添加。

另一种解决方案(处理%a和%b中不均匀散列元素)。

my %c; 

foreach my $key (keys %a, keys %b) { 
    my $a_ref = $a{$key}; 
    my $b_ref = $b{$key}; 
    $c{$key} = { map %$_, @$a_ref, @$b_ref }; 
} 

use Data::Dumper; 
print Dumper \%c;