2017-03-16 78 views
2

我想備份散列,保留原始散列,並使用備份的散列數據。散列副本和刪除perl

並刪除備份哈希數據。

但是,原始散列數據已被刪除。

這是代碼。

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 

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

我認爲這是一個散列引用問題。

如何保留原始散列並刪除備份散列?

+0

你是不是值複製,要複製引用。這只是創建更多的指向相同數據的指針。 – simbabque

回答

1

如果您爲新變量指定引用,則不會複製引用後面的值。相反,參考被複制。想象一下你有一張寫在紙上的書的名字。如果你給我一份這份文件的副本,我沒有得到這本書的副本,只有這本書的名字。

您需要複製每個單獨的參考。一個簡單的方法是從核心模塊Storabledclone

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

你需要實現的是多維數據結構在perl中的工作方式 - 它們通過引用工作。

所以你沒有哈希散列 - 你有散列哈希引用

嘗試:

print values %hash; 

或者

print $hash{data1}; 

你會看到類似這樣的:

HASH(0x33cff8) 

這是哪裏的$hash{one}參考價值。

你在做什麼是將參考添加到您的第二個散列。但結構是指......仍然是原來的一個:

print $hash_backup{data1}; 

還將打印:

HASH(0x33cff8) 

所以他們不是兩個單獨的數據結構 - 他們都指的是同樣的子哈希。

至於什麼解決方案是?那麼,這取決於你想要完成什麼。複製像這樣的散列不會像你所假設的那樣工作,所以你需要做別的事情。有多種克隆方法,例如使用Storable,或者只是「手動」遞歸鍵。但我建議先考慮你的目標是什麼,然後嘗試找到適合的東西。