2016-02-27 179 views
0

我想合併兩個哈希,並且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個元素的數組(一個散列引用),你可能會更好地使用帶有深元素的散列引用。只是一個觀察。 –

回答

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, 

代碼不處理的陣列/不相等的大小,但檢查的哈希可以容易地添加。

0

另一種解決方案(處理%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;