2016-05-10 19 views
0

我有兩個子程序按順序調用,在第一個子過程中,我需要過濾出哈希的特定鍵/值。我試過「刪除」,它的工作原理是從我的哈希中完全刪除該選項,但我也指第二個子例程中的同一個哈希。我需要鍵/值不能僅在sub1中提及。我怎樣才能做到這一點? 我的散列類似於此:在Perl中過濾特定的哈希標記

my $hash => { a => 123, 
      b => 234, 
      c => {option1 => 123, 
       option2 => 235}, 
     }; 

sub1 { 
    sub1 needs only hash values a and b 

    # the following is what I did. 
    my $c = delete($hash->{c}); 
} 

sub2 { 
    sub2 needs all a, b and c but after delete on $hash 
    I can only see a and b 
} 

SUB1和SUB2需要順序執行,在這種情況下,我該如何實現這一目標? 感謝任何幫助或指導。

在此先感謝。

+0

如果您可以提供您在每個子項目中嘗試完成的粗略示例,則可能會出現適當的解決方案。 –

回答

3

這是一個罕見的情況下,local可能是一個對您有用:

my $hash => { 
    a => 123, 
    b => 234, 
    c => { 
     option1 => 123, 
     option2 => 235, 
    }, 
}; 

sub sub1 { 
    # We only need hash values a and b 
    delete local $hash->{c}; 

    print "sub1: $_\n" for sort keys %$hash; 
} 

sub sub2 { 
    # sub2 needs all a, b and c. 

    print "sub2: $_\n" for sort keys %$hash; 
} 

sub1(); 
sub2(); 

的輸出將是

sub1: a 
sub1: b 
sub2: a 
sub2: b 
sub2: c 

關鍵字「本地」局部化的密鑰,以便將其刪除被撤銷時的範圍退出。 Perl的文檔中最好的解釋是perlsub: Localized deletion of elements of composite types

還有一點要提出的是,它通常是有益的參數傳遞到一個子程序,而不是從周邊範圍吸收他們:

my $hash = { 
    a => 'foo', 
    b => 'bar', 
    c => {baz => 'bang'}, 
}; 

sub sub1 { 
    my $href = shift; 
    delete local $href->{c}; 

    print "sub1: $_\n" for sort keys %$href; 
} 

sub sub2 { 
    my $href = shift; 
    print "sub2: $_\n" for sort keys %$href; 
} 

sub1($hash); 
sub2($hash); 

即使使用這樣的變化,在$href非本地化元素的修改將傳播回到$hash,因爲你通過引用傳遞。但它仍然是一個很好的習慣,因爲它提高了可讀性,並將子程序從周圍範圍的命名中解耦出來,這有望爲更多的可重用子文件做出貢獻。

偶爾有用的另一種技術是對傳入的結構進行深度克隆,以至於您可以自由修改克隆而不必將更改傳播回傳遞給子例程的指示對象。然而,如果元素包含對象而不是普通的舊值或嵌套值,則這可能是昂貴的(甚至不可能)。儘管如此,完整性我會提到Storable'sdclone功能,這可能會這樣使用:

use Storable qw(dclone); 

my $hash = { 
    a => 123, 
    b => 234, 
    c => {option1 => 123, option2 => 235}, 
}; 

sub sub1 { 
    my $href = shift; 
    my $clone = dclone($href); 
    delete $clone->{c}; 
    print "sub1: $_\n" for sort keys %$clone; 
} 

sub sub2 { 
    my $href = shift; 
    print "sub2: $_\n" for sort keys %$href; 
} 

sub1($hash); 
sub2($hash); 

dclone不是克隆一個數據結構的唯一途徑。您可以編寫自己的解決方案,更適合您的具體情況,特別是如果您事先知道結構的形狀和組成。但作爲一個通用的解決方案,它非常有用。

但最終dclone將創建一個全新的數據結構,而不是隻是暫時隱藏一個密鑰,這是delete local $href->{c}做的。如果您可以使用local來避免創建結構的副本,或者消除必須手動將值存入的錯誤和額外考慮的潛在來源(即my $temp = delete $href->{c}; ... $href->{c} = $temp;),那麼您已經找到了一個那些時候它變成了這個工作的正確工具。

0

有兩種基本的方法來做到這一點。

sub1創建一個臨時散:

my %hash = (
    a => 123, 
    b => 234, 
    c => { option1 => 123, option2 => 235}); 

sub1(\%hash); 
sub2(\%hash); 

sub sub1 
{ 
    my($hash) = @_; 
    my(%tmp); 

    # this [followed by delete below] is faster than grep, etc. 
    %tmp = %$hash; 
    $hash = \%tmp; 

    # sub1 needs only hash values a and b 
    # the following is what I did. 
    delete($hash->{c}); 

    # do stuff ... 
} 

sub sub2 
{ 
    my($hash) = @_; 

    # sub2 needs all a, b and c but after delete on $hash 
    # I can only see a and b 
} 

或者,在sub1刪除元素並在退出之前添加回去:

my %hash = (
    a => 123, 
    b => 234, 
    c => { option1 => 123, option2 => 235}); 

sub1(\%hash); 
sub2(\%hash); 

sub sub1 
{ 
    my($hash) = @_; 

    # sub1 needs only hash values a and b 
    # the following is what I did. 
    my $c = delete($hash->{c}); 

    # do stuff ... 

    # add it back 
    $hash->{c} = $c; 
} 

sub sub2 
{ 
    my($hash) = @_; 

    # sub2 needs all a, b and c but after delete on $hash 
    # I can only see a and b 
}