2009-10-09 35 views
22

可能重复:
What's the best way to make a deep copy of a data structure in 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'}都是完全相同的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) 
+2

如你所说,你得到了答案,你应该检查回答你的问题的帖子是正确的答案。 –

回答

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

总是可以通过存储可保存或数据::自卸车的哈希,并重新分配将存储的值转换为新的散列值。这应该得到一个完整的副本,而不会维护引用的链接。

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

这种情况下有特殊功能'dclone' –

29

从可保存:: dclone文档,我发现Clone

my $copy = clone (\@array); 

# or 

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

不需要灵活性,并声称自己是比Storable::dclone更快。

+2

基准显示这是dclone的两倍快 – Oesor

+0

看起来像这样不克隆线程:: shared data strucutre?无法通过包“threads :: shared :: tie”找到对象方法“FETCH” – ealeon

7

深层数据结构101:

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

Data :: Compare对我而言也是新的,我刚刚解开我的哈希来检查它们。我一定会尝试一下比较真正复杂的东西;谢谢 – Oesor

+1

Test :: Deep和Test :: Differences由于无处不在的Test :: More的新is_deeply功能而失宠 - 请检查一下。污垢使用简单,并且您会遇到一个很大的错误。 –

相关问题