26

重複の可能性:
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!
}

as$group{'item1'}$config{'group'}{'item1'}はどちらもまったく同じ hashref です。

構成ファイルを単純に再解析し、ディスクに保存する直前にディスクから解析されたコピーを編集済みのバージョンと比較するのは簡単ですが、複雑なデータ構造のネストされた逆参照への方法があると確信しています、単に参照自体をコピーするのではなく、ハッシュ参照の内容をコピーします。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)
4

4 に答える 4

37
use Storable qw(dclone);
$group2 = dclone(\%group);
于 2009-10-09T22:18:29.257 に答える
30

Storable::dclone ドキュメントからCloneを見つけました:

my $copy = clone (\@array);

# or

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

柔軟性は必要なく、 Storable::dcloneよりも高速であると主張しています。

于 2009-10-09T22:23:54.347 に答える
7

深いデータ構造 101:

  • Storableを使用して、構造のdcloneディープ コピーを作成し、それらをストレージ用freezethawシリアライズ/デシリアライズします (データベースや http Cookie など) (ただし、ユーザーに送信するものはすべて暗号化して、改ざんしにくくする必要があります)。
  • Data::Compare (または単体テスト内のTest::DeepまたはTest::Differences ) を使用して、2 つの深いデータ構造を比較します。
  • デバッグで Data ::DumperまたはData::Dumpを使用して、オブジェクトがどのように見えるかを確認します。ただし、それを別のオブジェクトの内部を改ざんするためのライセンスとして使用しないでください。API を使用します。:)
于 2009-10-09T22:33:19.723 に答える
-3

Storable または Data::Dumper を介して常にハッシュを格納し、格納された値を新しいハッシュに再割り当てできます。これは、参照されたリンクを維持せずに完全なコピーを取得する必要があります。

use Storable;
my $serialized = freeze \%config;
my %newconfig = %{ thaw($serialized) };
于 2009-10-09T22:19:01.953 に答える