【问题标题】:hash copy and delete in perlperl 中的哈希复制和删除
【发布时间】:2017-03-16 10:19:31
【问题描述】:

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

并删除了备份的哈希数据。

但是,原来的哈希数据已经被删除了。

这里是代码。

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

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

我认为是哈希引用问题。

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

【问题讨论】:

  • 您不是在复制值,而是在复制引用。这只会创建更多指向相同数据的指针。

标签: perl hash


【解决方案1】:

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

看这里:

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

【讨论】:

    【解决方案2】:

    如果将引用分配给新变量,则不会复制引用后面的值。相反,引用被复制。想象一下,您将一本书的名字写在一张纸上。如果你给我那篇论文的副本,我不会得到这本书的副本,只有引用这本书的名字。

    您需要复制每个单独的参考。一个简单的方法是使用核心模块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

    【讨论】:

      【解决方案3】:

      您需要了解的是多维数据结构在 perl 中的工作方式——它们通过引用工作。

      所以你没有散列的散列 - 你有散列 references 的散列。

      试试:

      print values %hash;
      

      或者

      print $hash{data1};
      

      你会看到类似的东西:

      HASH(0x33cff8)
      

      $hash{one} 的值在哪里引用。

      您正在做的是将 reference 添加到您的第二个哈希中。但它所指的结构……还是原来的那个:

      print $hash_backup{data1};
      

      还将打印:

      HASH(0x33cff8)
      

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

      至于解决方案是什么?好吧,这取决于您要完成的工作。复制这样的哈希不会按照您假设的方式工作,因此您需要做其他事情。有多种克隆方法,例如使用Storable,或者只是“手动”递归地遍历键。但我建议首先考虑你的目标是什么,然后尝试找到适合的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-18
        • 1970-01-01
        • 2013-08-31
        • 1970-01-01
        • 2016-03-28
        • 2017-01-11
        • 2011-06-01
        • 2023-04-09
        相关资源
        最近更新 更多