2011-08-08 17 views
3

非常にシンプルなように見えますが、そのほとんどを理解しました。 Perlなどの見する構文で緩んでいる。しかし、それはこれが右はperldocのWebサイトからであるに:)このperlスクリプトを理解しようとしています

my @unique =(); 
my %seen =(); 
foreach my $elem (@array) { 
    next if $seen{ $elem }++; 
    push @unique, $elem; 
} 

権利をジャンプする新人のために困難です。私が正しく理解していれば、それはのように書くこともできます。

my @unique =(); 
my %seen =(); 
my $elem; 
foreach $elem (@array) { 
    if ($seen{ $elem }++) { 
     next; 
    } 
    push (@unique, $elem); 
} 

したがって、この時点での私の理解では、次のとおりです。

  • ユニーク
  • という名前の配列が
  • 宣言を見て名前のハッシュを宣言宣言しますelemという名前の変数
  • 各繰り返しは$ elemに格納されます。
  • $ elemがハッシュのキー

    • :%私は2つのことを欠けている@Unique

    の最後に次の反復

  • 追加の$ ELEMにスキップし、(私は++が何をするか分からない)見何も%で保存されていますか?

    私は疑う
    $seen{ $elem }++ 
    

    :私は問題はこの部分であることを知ってい++(それがインクリメント他のすべての言語で、私はそれがどのように機能するかを見ていけない)やる

  • 一度にさまざまなものをやっています。その行を書くためにもっと簡単な方法がありますか?それはそれを持っている他のほとんどの言語の場合のように助けを

    おかげ

  • 答えて

    4

    ++オペレータはPerlで、本質的に同じことを行います。それは、変数をインクリメントします。

    $seen{ $elem }++; 
    

    %seenの値は、そのキー$elemである、すなわち一つを有するインクリメントします。

    「マジック」は、$seen{$elem}がまだ定義されていない場合は、あたかもすでに存在していて、値が0のように自動的に作成されます。これは、「autovivification」と呼ばれている

    if (! exists $seen{$elem}) { 
        $seen{$elem} = 0; 
    } 
    $seen{$elem} ++; 
    

    ++は、だからと同等だこれを1に設定します。 (編集2:いいえ、私の間違いではありません; @ysthが指摘しているように、「自動化」とは実際にはの参照を意味します。が現れます。perldoc perlrefを参照してください。)

    EDIT:

    • スカラー変数を宣言し
    • ハッシュ変数命名%を宣言
    • @Uniqueという名前配列変数を宣言します。ここでは、あなたの記述の改訂版です $ elem
    • @arrayで繰り返し、各繰り返しは$ elemに格納されます
    • の$ elemはが見ハッシュ%で鍵となる、@Unique

    @uniqueの最後に次の反復

  • 追加の$ ELEMの値を飛ばし、%seen、および$elemがすべてある場合変数。 「印章」として知られている句読点文字は(変数の種類、それらのそれぞれは、名前の一部としての最高の考えを何であるかを示します。

  • +0

    ああ私は何か魚が巻き込まれていると思った。多くの自動化されたコードを書くのは良い習慣ですか?それとも、それを長い道のりで書く方が良いでしょうか? – n0pe

    +2

    @MaxMackie:Perlにコード化された理由は、Larry Wallがそれが役に立つパターンであることを知っていたからです。一度あなたがそれを知っている、それは多くの意味があります。このようなコードでは、ハッシュ値の数値演算しか行っていないので、ハッシュの値を0で始まったかのように扱うのが理にかなっています。真(ゼロ以外)、決してこれは大丈夫な仮定であり、コードを単純化することができます。 –

    +0

    完璧、あなたの助けに感謝します。私は2分で受け入れます。 – n0pe

    3

    何かが見え%に格納されますない場合は?

    それをインクリメントしようとします。

    ++何を(それがインクリメントし、他のすべての言語で、私はそれがどのように機能するかを見ていけない)やるん

    未定義の変数をインクリメントすること1

    なりますそれは、このように同じことを:

    my @unique =(); 
    my %seen =(); 
    my $elem; 
    foreach $elem (@array) { 
        if (! $seen{ $elem }) { 
         $seen{ $elem } = 1; 
        } else { 
         $seen{ $elem }++; 
         push (@unique, $elem); 
        } 
    } 
    
    1

    キーの$ elemはと見られ%で要素がない場合、この行は、新しい要素(新しいを作成します。ハッシュテーブル内のエントリ)をキー$ elemで置き換えます。その後の++はインクリメント演算子です。これは、$ seen {$ elem}の値が何であれ、それを追加します。 $ seen {elem}の初期値は数値であるので、falseと評価されるので、$ seen {elem}の値は1だけ増加します。 ++は$ seen {elem}の右側にあるので、$ seen {elem}が評価された後にのみ追加されます。したがって、最初に特定の$ elemに遭遇すると、このテストは失敗し、次のステップに進み、$ elemを一意の要素のリスト(配列)に入れます。

    3

    これは、指定された配列内の "ユニークな"要素からなる配列を作成するためのPerlの一般的なパターンです。

    ハッシュは、任意のキーに関連付けられた値を格納します。ただし、指定されたキーのハッシュに何も入れていない場合は、undefが得られますが、インクリメント操作などの数値コンテキストでは、は0のように扱われ、インクリメントされます。

    ifステートメントは、わかっているとおり、真偽値をチェックします。 Perlでは、0,"0",''(空文字列)、およびundef(おそらく他の?)が偽値として扱われます。

    C/C++/Javaの場合と同様に、ポストインクリメントは、元の値を含む式に返します。だから、このコード

    if ($seen{ $elem }++) { 
         next; 
        } 
    

    は(すなわち、next文が実行されません)まだ見られていない、とループが継続する要素について(0)falseを返します。要素が配列に配置されます。しかし、それが起こる前に、インクリメントが発生します - 今では、突然1がハッシュに格納されます。これは値が一度見られたことを意味します。次回その値が表示されると、ループはスキップされ、値は結果配列に再度追加されません。

    関連する問題