web-dev-qa-db-ja.com

Perlでハッシュのハッシュをディープコピーする最良の方法は何ですか?

可能性のある複製:
Perlでデータ構造のディープコピーを作成する最良の方法は何ですか?

これを自分でコーディングしてホイールを再発明する前に、ハッシュリファレンスを複製せずにハッシュのハッシュをどのようにコピーしますか?

Config :: General でハッシュのハッシュのハッシュを読んでいます。つまり、データ構造は次のとおりです。

my %config = ( group => { item1 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item2 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item3 => { foo => 'value',
                                     bar => 'value',
                                   },
                        },
             );

次に、グループを逆参照して構成からグループを引き出し、実行時に構成ファイルを書き換える前に内容を変更します。

my %group = %{$config{'group'}};

問題は、変更が行われたかどうかを確認し、システムのファイル構造に関連する変更を加える必要があることです。私はこれを確認することはできません:

if ($group{'item1'}{'foo'} ne $config{'group'}{'item1'}{'foo'}) {
    ### Stuff!
}

なので $group{'item1'}および$config{'group'}{'item1'}は両方ともまったく同じハッシュリファレンスです。

単純に構成ファイルを再解析し、ディスクから解析したコピーを編集したバージョンとディスクに保存する直前に比較することは簡単ですが、複雑なデータ構造のネストされた逆参照を行う方法があると確信しています、単に参照自体をコピーするのではなく、ハッシュ参照の内容をコピーします。 CPANのざっと調べても何も起こりません。何が欠けていますか?

ベンチマーク

私の答えを得ました:

#!/usr/bin/Perl

use Benchmark qw(:all) ;
use Storable qw(dclone);
use Clone qw(clone);

my %config = ( group => { item1 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item2 => { foo => 'value',
                                     bar => 'value',
                                   },
                          item3 => { foo => 'value',
                                     bar => 'value',
                                   },
                        },
             );

my $ref = $config{'group'};

timethese(100000, {
  'Clone' => sub { my %group = %{ clone $ref }},
  'Storable' => sub {  my %group = %{ dclone $ref }},
});

結果は:

ベンチマーク:クローンの100000反復のタイミング、保存可能... 
クローン:2ウォールクロック秒(2.26 usr + 0.01 sys = 2.27 CPU)@ 44052.86/s(n = 100000) ]保存可能:5ウォールクロック秒(4.71 usr + 0.02 sys = 4.73 CPU)@ 21141.65/s(n = 100000)
24
Oesor
use Storable qw(dclone);
$group2 = dclone(\%group);
37
codehead

私が見つけたStorable :: dcloneドキュメントから Clone

my $copy = clone (\@array);

# or

my %copy = %{ clone (\%hash) };

柔軟性は必要ありません、そして Storable :: dclone より速いと主張します。

30
Oesor

深いデータ構造101:

  • Storabledcloneを使用して構造のディープコピーを作成し、freezethawを使用して、それらをストレージ用にシリアル化/非シリアル化します(たとえば、データベース、またはhttp cookie(ただし、改ざんを困難にするために、ユーザーに送信するすべてのものを暗号化する必要があります)。
  • 2つのディープデータ構造を比較するには、 Data :: Compare (または Test :: Deep または Test :: Differences ユニットテスト内)を使用します。
  • オブジェクトの外観を確認するには、デバッグで Data :: Dumper または Data :: Dump を使用します。しかし、別のオブジェクトの内部を改ざんするためのライセンスとしてそれを使用しないでください。 APIを使用します。 :)
7
Ether