2016-05-10 7 views
0

私は2つのサブルーチンを順に呼びます。最初のサブルーチンでは、特定のキー/ハッシュ値をフィルタリングする必要があります。私は "削除"しようとし、それは私のハッシュからそのオプションを完全に削除する場所で動作しますが、私はまた、2番目のサブルーチンで同じハッシュを参照しています。私は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に戻ります。しかし、それは可読性を向上させ、周囲のスコープの名前からサブルーチンを切り離すので、やり直すのは良い習慣です。

時には便利なもう1つの手法は、渡された構造の深いクローンを作成することです。サブルーチンに渡された参照先に変更が反映されずにクローンを自由に変更できることです。しかし、エレメントにプレーンな古い値またはネストされた値ではなくオブジェクトが含まれている場合、これは高価(または不可能)になる可能性があります。

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は、データ構造のクローンを作成するための唯一の方法ではありません。それにもかかわらず、完全を期すために、私はこのように使用される可能性がありますStorable'sdclone機能を、言及します。特定のケースに適した独自のソリューションを作成することができます。特に、事前に構造の形状と構成を知っている場合は、しかし、一般的な解決策として、それはかなり便利です。

しかし、最終的にdcloneは、ただちに鍵を隠すのではなく、まったく新しいデータ構造を作成することになります。これはdelete local $href->{c}の機能です。 localを使用して構造体のコピーを作成する必要性を避けることができ、あるいは誤差や余分な思考の潜在的な原因を排除して、手作業で値を保存する必要がある場合(つまり、my $temp = delete $href->{c}; ... $href->{c} = $temp;)仕事のための正しいツールであると判明した時代。

0

を見て、また

sub sub1 { 
    my %new_hash; 
    my @keys = grep { $_ ne 'c' } keys %$hash; 
    @new_hash{@keys} = @$hash{@keys}; 
    return \%new_hash; 
} 

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 
} 
関連する問題