在Perl中深度复制哈希散列的最佳方法是什么?

时间:2009-10-09 22:14:14

标签: perl deep-copy

  

可能重复:
  What's the best way to make a deep copy of a data structure in Perl?

在我开始自己编写代码并重新发明轮子之前,如何在不复制hashref的情况下复制哈希散列?

我正在通过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'}都是完全相同的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 }},
});

结果:

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)

4 个答案:

答案 0 :(得分:35)

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

答案 1 :(得分:30)

从Storable :: dclone文档中我发现Clone

my $copy = clone (\@array);

# or

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

不需要灵活性,声称速度比Storable::dclone快。

答案 2 :(得分:7)

深度数据结构101:

  • 使用Storabledclone制作结构的深层副本,并使用freezethaw对其进行序列化/反序列化以进行存储(例如在数据库中,或者是一个http cookie(但你应该加密发送给用户的任何内容,以免篡改)。
  • 在单元测试中使用Data::Compare(或Test::DeepTest::Differences)来比较两个深层数据结构。
  • 在调试中使用Data::DumperData::Dump来查看对象的外观。但是,不要将其用作篡改另一个对象内部的许可证;使用API​​。 :)

答案 3 :(得分:-3)

可以始终通过Storable或Data :: Dumper存储哈希值,并将存储的值重新分配给新的哈希值。这应该得到一个完整的副本,而不维护引用的链接。

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