在perl中进行散列复制和删除

时间:2017-03-16 10:19:31

标签: perl hash

我想备份哈希,保留原始哈希,并使用备份的哈希数据。

删除了备份哈希数据。

但是,原始哈希数据已被删除。

这是代码。

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

================================

我认为这是一个哈希引用问题。

如何保留原始哈希并删除备份哈希?

3 个答案:

答案 0 :(得分:1)

如果为新变量分配引用,则不会复制引用后面的值。而是复制引用。想象一下,你有一本书写在一张纸上的名字。如果你给我一份那份文件的副本,我就不会得到这本书的副本,只有参考书的名字。

您需要复制每个参考文献。一种简单的方法是使用核心模块Storable中的dclone

use Storable 'dclone';
my %hash_backup = %{ dclone(\%hash) };

如果您的数据结构平均小于三个级别,您可能需要查看Clone,它声称速度更快。

use Clone 'clone';
my %hash_backup = %{ clone(\%hash) };

在这两种情况下,都需要参考。因为您需要哈希而不是哈希引用,所以您需要传递新的引用\%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
}

我建议你阅读perlrefperlreftut

答案 1 :(得分:1)

你需要意识到的是多维数据结构在perl中的工作方式 - 它们通过引用工作。

所以你没有哈希哈希 - 你有哈希引用的哈希

尝试:

print values %hash;

或者

print $hash{data1};

你会看到类似的东西:

HASH(0x33cff8)

$hash{one}的值引用的位置。

您正在做的是将引用添加到您的第二个哈希。但它所指的结构......仍然是最初的结构:

print $hash_backup{data1};

还会打印:

HASH(0x33cff8)

所以他们不是两个独立的数据结构 - 他们都指的是同一个子哈希。

关于解决方案是什么?嗯,这取决于你想要完成的事情。复制像这样的哈希并不像你假设的那样工作,所以你需要做一些其他事情。有各种克隆方法,例如使用Storable,或者只是递归地手动操作按键'。但我建议首先考虑你的目标是什么,并尝试找到合适的东西。

答案 2 :(得分:1)

您需要deep copyclone来复制完整哈希,而不仅仅是第一级元素。

见这里:

What's the best way to deep copy a hash of hashes in Perl?