可能重复:
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)
答案 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:
dclone
制作结构的深层副本,并使用freeze
和thaw
对其进行序列化/反序列化以进行存储(例如在数据库中,或者是一个http cookie(但你应该加密发送给用户的任何内容,以免篡改)。答案 3 :(得分:-3)
可以始终通过Storable或Data :: Dumper存储哈希值,并将存储的值重新分配给新的哈希值。这应该得到一个完整的副本,而不维护引用的链接。
use Storable;
my $serialized = freeze \%config;
my %newconfig = %{ thaw($serialized) };