我想备份哈希,保留原始哈希并使用备份的哈希数据。
并删除了备份哈希数据。
但是,原始哈希数据已删除。
这是代码。
my %hash = (
'data1' => {
'data2' => {
'data3' => 'one',
},
},
);
foreach (1..3) {
my %hash_backup = %hash;
print $hash{'data1'}->{'data2'}->{'data3'},"n";
print $hash_backup{'data1'}->{'data2'}->{'data3'},"n";
print "-------------------------------n";
delete $hash_backup{'data1'}->{'data2'};
print $hash{'data1'}->{'data2'}->{'data3'},"n";
print $hash_backup{'data1'}->{'data2'}->{'data3'},"n";
print "================================n";
}
结果,
one
one
-------------------------------
================================
-------------------------------
================================
-------------------------------
================================
如果更改删除代码,则可以正常工作。
delete $hash_backup{'data1'};
结果,
one
one
-------------------------------
one
================================
one
one
-------------------------------
one
================================
one
one
-------------------------------
one
================================
我认为这是一个哈希参考问题。
如何保留原始哈希并删除备份哈希?
您需要deep copy
或clone
来复制完全哈希,而不仅仅是元素的第一级。
请参阅此处:
深层复制perl中的哈希的最佳方法是什么?
如果将引用分配给新变量,则不复制引用背后的值。相反,参考被复制。想象一下,您的名字是写在一张纸上的书。如果您给我一份论文的副本,我不会得到这本书的副本,只有引用该书的名称。
您需要复制每个参考。一种简单的方法是使用dclone
从核心模块存储中。
use Storable 'dclone';
my %hash_backup = %{ dclone(%hash) };
如果您的数据结构平均小于三个级别,则您可能想查看克隆,该克隆声称其更快。
use Clone 'clone';
my %hash_backup = %{ clone(%hash) };
在这两种情况下,都可以参考。因为您想要哈希,而不是哈希参考,所以您需要传递新的ref %foo
并在出口 %{ ... }
中取消。
如果您想自己执行此操作,则必须走数据结构,复制每个参考。要强制Perl制作数据的副本,而不是参考,您需要取消并创建一个新的参考。
use strict;
use warnings;
use Data::Printer;
my $foo = { foo => 'bar' };
my $bar = { %$foo };
$bar->{foo} = 123;
p $foo;
p $bar;
此输出
{
foo "bar"
}
{
foo 123
}
我建议您阅读Perlref和Perlreftut。
您需要意识到的是多维数据结构在Perl中起作用的方式 - 它们通过参考来工作。
因此您没有哈希 - 您有哈希参考的哈希。
尝试:
print values %hash;
或
print $hash{data1};
您会看到类似的东西:
HASH(0x33cff8)
这是$hash{one}
参考值的值。
您正在做的是在您的第二个哈希中添加参考。但是它指的是...仍然是原始的:
print $hash_backup{data1};
也将打印:
HASH(0x33cff8)
因此,它们不是两个单独的数据结构 - 它们都指的是同一子锤子。
关于解决方案是什么?好吧,这取决于您要完成的工作。复制这样的哈希人无法按照您的假设方式工作,因此您需要做其他事情。克隆它有多种方法,例如使用Storable
,或者只是"手动"递归地行走钥匙。但是我建议首先考虑您的目标是什么,然后尝试找到适合的东西。