Perl 模組 Hash::Merge
簡介
把兩個任意深度的hash合併成一個。
使用方式如下:
use Hash::Merge qw( merge );
my %a = (
'foo' => 1,
'bar' => [ qw( a b e ) ],
'querty' => { 'bob' => 'alice' },
);
my %b = (
'foo' => 2,
'bar' => [ qw(c d) ],
'querty' => { 'ted' => 'margeret' },
);
my %c = %{ merge( \%a, \%b ) };
Hash::Merge::set_behavior( 'RIGHT_PRECEDENT' );
# This is the same as above
Hash::Merge::specify_behavior(
{
'SCALAR' => {
'SCALAR' => sub { $_[1] },
'ARRAY' => sub { [ $_[0], @{$_[1]} ] },
'HASH' => sub { $_[1] },
},
'ARRAY => {
'SCALAR' => sub { $_[1] },
'ARRAY' => sub { [ @{$_[0]}, @{$_[1]} ] },
'HASH' => sub { $_[1] },
},
'HASH' => {
'SCALAR' => sub { $_[1] },
'ARRAY' => sub { [ values %{$_[0]}, @{$_[1]} ] },
'HASH' => sub { Hash::Merge::_merge_hashes( $_[0], $_[1] ) },
},
},
'My Behavior',
);
# Also there is OO interface.
my $merge = Hash::Merge->new( 'LEFT_PRECEDENT' );
my %c = %{ $merge->merge( \%a, \%b ) };
# All behavioral changes (e.g. $merge->set_behavior(...)), called on an object remain specific to that object
# The legacy "Global Setting" behavior is respected only when new called as a non-OO function.
詳情
在任何層級,都只從一個hash結構合併無衝突的鍵值對到另一個hash結構,如果遇到衝突的結構則會根據特定的配置進行處理。因為hash結構是可以深度巢狀的,所以任何層級的hash結構都會被使用同樣的方法進行遞迴的合併。
注:自引用的hash,或是巢狀引用的hash都無法被正確的處理。
在hash結構中的值,會被當成hashref、arrayref或scalar來處理。預設情況下,在進行合併之前,會先使用Clone
模組對資料進行“克隆”得到一個副本,然後對資料的副本進行合併操作。當然了,如果有必要我們可以改變這種預設行為,使用原始資料進行合併操作。(引數set_clone_behavior
方法)
由於在很多時候,即使hash的鍵值產生了衝突使用者也想要進行正解的合併;Hash::Merge
為使用者提供了幾常用的處理方式,並且也預留了供使用者自己的擴充套件的介面。詳情如下:
Left Precedence(左值優先)
這是預設行為。
在這種配置下,繫結在左值上的hash永遠不會丟失。所有正常(沒有衝突)的右值都會被合併到左值上。
my $merge = Hash::Merge->new();
my $merge = Hash::Merge->new('LEFT_PRECEDENT');
$merge->set_set_behavior('LEFT_PRECEDENT')
Hash::Merge::set_set_behavior('LEFT_PRECEDENT')
Right Precedence(右值優先)
和“左值優先”一樣,只是這裡是右值上的hash永遠不會丟失,並且所有正常(沒有衝突)的左值都會被合併到右值上。
my $merge = Hash::Merge->new('RIGHT_PRECEDENT');
$merge->set_set_behavior('RIGHT_PRECEDENT')
Hash::Merge::set_set_behavior('RIGHT_PRECEDENT')
Storage Precedence(儲存優先)
如果衝突的鍵有兩個不同型別的值,則更“大”的型別的會被保留下來。array比scalar更“大”,hash比其他其他型別都“大”。這時,較“小”的型別會嘗試合併到較大的型別中,如果無法合併,較“小”型別的資料會被丟棄。
my $merge = Hash::Merge->new('STORAGE_PRECEDENT');
$merge->set_set_behavior('STORAGE_PRECEDENT')
Hash::Merge::set_set_behavior('STORAGE_PRECEDENT')
Retainment Precedence(Retainment 優先)
在這種行為下,不會有任何值丟失。scalar會被加入到陣列中,scalar和array都可以填充到hash中。
my $merge = Hash::Merge->new('RETAINMENT_PRECEDENT');
$merge->set_set_behavior('RETAINMENT_PRECEDENT')
Hash::Merge::set_set_behavior('RETAINMENT_PRECEDENT')
方法說明
merge(<hashref>,<hashref)
使用特定的規則把兩個hash合併成一個新的hash,並返回。
_hashify( <scalar>|<arrayref> ) -- INTERNAL FUNCTION
返回一個從 scalar 和 array 建立的hash;為每個scalar或array中的每一個元素建立一個鍵值對,鍵和值都是它本身。
_hashify(3) ## {3=>3}
_hashify([2,3]) ## {2=>2,3=>3}
_merge_hashes( <hashref>, <hashref> ) -- INTERNAL FUNCTION
實際上是針對每個 key 的 value 重複呼叫 merge
方法。
sub _merge_hashes {
my $self = &_get_obj; # '&' + no args modifies current @_
my ( $left, $right ) = ( shift, shift );
if ( ref $left ne 'HASH' || ref $right ne 'HASH' ) {
carp 'Arguments for _merge_hashes must be hash references';
return;
}
my %newhash;
foreach my $leftkey ( keys %$left ) {
if ( exists $right->{$leftkey} ) {
$newhash{$leftkey} = $self->merge( $left->{$leftkey}, $right->{$leftkey} );
}
else {
$newhash{$leftkey} = $self->{clone} ? $self->_my_clone( $left->{$leftkey} ) : $left->{$leftkey};
}
}
foreach my $rightkey ( keys %$right ) {
if ( !exists $left->{$rightkey} ) {
$newhash{$rightkey} = $self->{clone} ? $self->_my_clone( $right->{$rightkey} ) : $right->{$rightkey};
}
}
return \%newhash;
}
set_clone_behavior( <scalar> )
在合併之前,資料是否被複制。如果是 true ,則在合併前會複製原始資料得到副本,並對副本進行合併。如果是 false,則直接對原始資料進行合併。預設情況下是 true。
get_clone_behavior( )
返回當前的 複製 行為的配置。
set_behavior( <scalar> )
指定具體的 合併 行為。引數 scalar 必須是已經定義的值,如:LEFT_PRECEDENT, RIGHT_PRECEDENT,STORAGE_PRECEDENT,RETAINMENT_PRECEDENT
get_behavior( )
返回當前正在被Hash::Merge使用的 行為 配置。
specify_behavior( <hashref>, [<name>] )
為 Hash::Merge 指定一個自定義的合併行為。hashref 必須定義3個鍵(SCALAR,ARRAY,HASH)。其中每個鍵的值同樣是一個包含三個鍵(SCALAR,ARRAY,HASH)的hash,不僅如此,並且內層hashref每個鍵的值都必須是一個 coderefs 。這些 coderefs 被呼叫時會傳兩個引數(左值和右值),它的功能就是合併這兩個值,並返回一個scalar,arrayref或hashref。如果有必要,可以使用函式_hashify和_merge_hashes作為這些輔助函式。
例如,你想新增左值標量到右值的陣列中,你可以有你的行為規範包括:
%spec = ( ...SCALAR => { ARRAY => sub { [ $_[0], @$_[1] ] }, ... } } );
內建行為
下面這些是每個內部行為在各種情況下如何工作的說明,其中$a是左值,$b是右值。
LEFT TYPE RIGHT TYPE LEFT_PRECEDENT RIGHT_PRECEDENT
SCALAR SCALAR $a $b
SCALAR ARRAY $a ( $a, @$b )
SCALAR HASH $a %$b
ARRAY SCALAR ( @$a, $b ) $b
ARRAY ARRAY ( @$a, @$b ) ( @$a, @$b )
ARRAY HASH ( @$a, values %$b ) %$b
HASH SCALAR %$a $b
HASH ARRAY %$a ( values %$a, @$b )
HASH HASH merge( %$a, %$b ) merge( %$a, %$b )
LEFT TYPE RIGHT TYPE STORAGE_PRECEDENT RETAINMENT_PRECEDENT
SCALAR SCALAR $a ( $a ,$b )
SCALAR ARRAY ( $a, @$b ) ( $a, @$b )
SCALAR HASH %$b merge( hashify( $a ), %$b )
ARRAY SCALAR ( @$a, $b ) ( @$a, $b )
ARRAY ARRAY ( @$a, @$b ) ( @$a, @$b )
ARRAY HASH %$b merge( hashify( @$a ), %$b )
HASH SCALAR %$a merge( %$a, hashify( $b ) )
HASH ARRAY %$a merge( %$a, hashify( @$b ) )
HASH HASH merge( %$a, %$b ) merge( %$a, %$b )
注:merger 表示呼叫了 _merge_hashes, hashify 表示呼叫了 _hashify。
示例
稍候更新,請關注。
相關文章
- perl 陣列的hash表陣列
- HASH JOIN ,MERGE JOIN ,NESTED LOOPOOP
- perl Statistics::Descriptive Perl 的統計模組
- nested loop,sort merge join,hash joinOOP
- Perl的包和模組
- Perl模組之Tie::File
- perl cpan 模組安裝
- perl的hash轉json後按key排序JSON排序
- HASH JOIN ,MERGE JOIN ,NESTED LOOP(R2)OOP
- HASH JOIN ,MERGE JOIN ,NESTED LOOP的比較OOP
- 【ningoo】編寫Perl模組Go
- 使用CPAN安裝Perl模組
- Nginx通過內建的Perl模組執行Perl程式Nginx
- perl的包(package)和模組(PM)Package
- Perl5的包和模組
- 測試mod_perl模組(轉)
- 比較perl模組的版本(轉)
- hash join\nest loop join\sort merge join的實驗OOP
- Perl 多執行緒模組 Parallel::ForkManager執行緒Parallel
- Oracle Hint:USE_NL、USE_MERGE、UESE_HASH(原理)Oracle
- 表的連線方式:NESTED LOOP、HASH JOIN、SORT MERGE JOIN(轉)OOP
- 【NinGoo】Redhat上安裝Perl DBD::mysql模組GoRedhatMySql
- Perl網路程式設計的10個模組程式設計
- Perl的一些重要模組使用介紹
- Python模組學習:hashlib hash加密Python加密
- 【NinGoo】用Perl的hash陣列實現個性化監控Go陣列
- 【江楓】用Perl的hash陣列實現個性化監控陣列
- 受限制環境安裝Perl模組方法(轉)
- 多表連線的三種方式詳解 hash join、merge join、 nested loopOOP
- strawberry perl安裝,環境變數及模組安裝變數
- 查詢自己機子上是否有某一Perl模組
- Nested loops、Hash join、Sort merge join(三種連線型別原理、使用要點)OOP型別
- perl
- DBI 資料庫模組剖析:Perl DBI 資料庫通訊模組規範,工作原理和例項資料庫
- 使用了一下perl的XML::Smart模組,真是太好用了XML
- CentOS 6.5安裝perl模組報錯'Can't locate ExtUtils/Manifest.pm'CentOS
- perl教程
- hash