[perl]ハッシュ(連想配列)のマージ
- 2007.08.04 Saturday
- dev
perlのハッシュ(連想配列)のマージについてちょっと調べました。自分用のメモとして記録しておきます。
一番直観的な方法は以下のようなコードでしょう。
%hash = (%hash, %addition);
ハッシュ
に対して、%hash
の内容を追加します。%addition
my %hash = ( 'key1' => 'value1', 'key2' => 'value2', ); my %addition = ( 'key3' => 'value3', 'key4' => 'value4', 'key1' => 'override1', ); %hash = (%hash, %addition);
上述のようなコードを実行すると、
の内容は以下のようになります。%hash
'key1' => 'override1', 'key2' => 'value2', 'key3' => 'value3', 'key4' => 'value4',
の内容が上書きされているのがポイント。key1
や while
でループを回してハッシュをマージする方法も利用できます。foreach
と while
を組み合わせると、以下のようなコードになります。each
while (my($key,$val) = each (%addition)) { $hash{$key} = $val; }
と foreach
を組み合わせて、以下のような方法でもマージできます。keys
foreach my $key (keys %addition) { $hash{$key} = $addition{$key}; }
同様の操作は
を使っても可能です。map
map { $hash{$_} = $addition{$_} } keys %addition;
最後にスライスを使う方法もあります。スライスを使い慣れた人には、ぱっと書けると思うのですが、私にはすぐには書けませんでした。
@hash { keys %addition } = values %addition;
ではなく、%hash
と記述します。@hash
ハッシュのリファレンスを利用した場合も同様に記述できます。
# normal merge $hash = {%{$hash}, %addition}; # use while while (my($key,$val) = each (%addition)) { $hash->{$key} = $val; } # use foreach foreach my $key (keys %addition) { $hash->{$key} = $addition{$key}; } # use map map { $hash->{$_} = $addition{$_} } keys %addition; # use slice @{$hash} { keys %addition } = values %addition;
速度がどの程度違うのか、調べてみました。
利用したコードは「続き」に記載しています。
foreach: 4 wallclock secs ( 4.17 usr + 0.00 sys = 4.17 CPU) @ 119904.08/s (n=500000) map: 5 wallclock secs ( 3.96 usr + 0.00 sys = 3.96 CPU) @ 126262.63/s (n=500000) merge: 7 wallclock secs ( 6.66 usr + 0.01 sys = 6.67 CPU) @ 74962.52/s (n=500000) slice: 5 wallclock secs ( 4.32 usr + 0.01 sys = 4.33 CPU) @ 115473.44/s (n=500000) while: 5 wallclock secs ( 4.35 usr + 0.01 sys = 4.36 CPU) @ 114678.90/s (n=500000)
使うなら、map でしょうか。
スライスを利用した方法も、マージするハッシュの内容によって速くなる場合がありましたが、具体的な条件が分かりませんでした。
従って、手元の簡単な調査では
によるマージが比較的安定した結果を出すという印象です。map
use Benchmark; timethese( 500000, { 'merge' => sub { my %hash = ( 'key1' => 'value1', 'key2' => 'value2', ); my %addition = ( 'key3' => 'value3', 'key4' => 'value4', 'key1' => 'override1', ); %hash = (%hash, %addition); }, 'while' => sub { my %hash = ( 'key1' => 'value1', 'key2' => 'value2', ); my %addition = ( 'key3' => 'value3', 'key4' => 'value4', 'key1' => 'override1', ); while (my($key,$val) = each (%addition)) { $hash{$key} = $val; } }, 'foreach' => sub { my %hash = ( 'key1' => 'value1', 'key2' => 'value2', ); my %addition = ( 'key3' => 'value3', 'key4' => 'value4', 'key1' => 'override1', ); foreach my $key (keys %addition) { $hash{$key} = $addition{$key}; } }, 'map' => sub { my %hash = ( 'key1' => 'value1', 'key2' => 'value2', ); my %addition = ( 'key3' => 'value3', 'key4' => 'value4', 'key1' => 'override1', ); map { $hash{$_} = $addition{$_} } keys %addition; }, 'slice' => sub { my %hash = ( 'key1' => 'value1', 'key2' => 'value2', ); my %addition = ( 'key3' => 'value3', 'key4' => 'value4', 'key1' => 'override1', ); @hash { keys %addition } = values %addition; }, } );
スポンサーリンク