Подтвердить что ты не робот

Какой лучший способ глубоко скопировать хэш хэшей в Perl?

Возможный дубликат:
Каков наилучший способ сделать глубокую копию структуры данных в Perl?

Прежде чем я начну кодировать это сам и заново изобретать колесо, как вы копируете хэш хэшей, не дублируя hashrefs?

Я читаю хэш хэш хэшей через 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 ничего не меняет. Что мне не хватает?

Benchmark

Получил свой ответ:

#!/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 }},
});

приводит к:

Benchmark: timing 100000 iterations of Clone, Storable...
   Clone:  2 wallclock secs ( 2.26 usr +  0.01 sys =  2.27 CPU) @ 44052.86/s (n=100000)
Storable:  5 wallclock secs ( 4.71 usr +  0.02 sys =  4.73 CPU) @ 21141.65/s (n=100000)
4b9b3361

Ответ 1

use Storable qw(dclone);
$group2 = dclone(\%group);

Ответ 2

В документации Storable:: dclone я нашел Clone:

my $copy = clone (\@array);

# or

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

Не требуется гибкость и утверждает, что он быстрее, чем Storable:: dclone.

Ответ 3

Глубокая структура данных 101:

  • Используйте Storable dclone, чтобы сделать глубокую копию структуры и freeze и thaw для сериализации/десериализации их для хранения (скажем, в базе данных или в http файле cookie (но вы должны шифровать все, что вы отправляете пользователю, чтобы затруднить вмешательство).
  • Используйте Data::Compare (или Test::Deep или Test::Differences внутри unit test), чтобы сравнить две глубокие структуры данных.
  • Используйте Data::Dumper или Data::Dump в отладки, чтобы увидеть, как выглядят ваши объекты. Но не используйте это как лицензию на вмешательство в другие объекты; используйте API.:)

Ответ 4

Может всегда хранить хэш через Storable или Data:: Dumper и переназначать сохраненное значение в новый хеш. Это должно получить полную копию, не поддерживая ссылки, ссылки.

use Storable;
my $serialized = freeze \%config;
my %newconfig = %{ thaw($serialized) };