配列内の重複しているデータを削除して(1つにまとめて)取り出す。[grep]

my @array = ('l', 'e', 'i', 'l', 'a');
my %count;
@array = grep( !$count{$_}++, @array ) ;


print @array;
⇒出力は『leia』



なんとなーくやってる事は解るけれど、
見ただけだとちゃんと理解できない。。
grepと !$count{$_}++ の意味がよく解らないの。

という訳で、少し分解。


= = = = = = = = 


@test = ('dummy', 'test', 'ddummyy') ;
@array = grep(/dummy/, @test) ;


grepは真偽を判断して、真の値のみを返す。
↑の場合は、@testの要素を1つずつ『dummy』と比較して
『dummy』が含まれていたら「真」、含まれていなかったら「偽」を返す。

⇒結果、@arrayには「真」のデータだけ返されるから
 @array = ('dummy', 'ddummyy') ;



という知識の元に、今回の例を見てみる。


!$count{$_}++ と @array の要素を比較して・・・
まだ要素が登場したことがなければ「真」、
既に登場済みなら「偽」を返している。はず。


解らないので更に分解。


$count{$_}++ ⇒ $count{$_} = $count{$_} +1
         変数の後に++と書く場合は、処理後に加算するから
         実質比較している内容は$count{$_}
$_ ⇒ デフォルト変数(最近やっと覚えた・・・)で、今だと@arrayの比較中の要素。


ふむふむ。
・・・$count{$_} が @arrayの要素と・・・どうすると「真」??


ということで、もう一度grepに戻る。
さっきの例だと『含まれていた時』に「真」と書いたけれど、正しくは
「1」=「真」 「0」=「偽」という判別をしている、という事が判明。


よーするに、
@test要素(例えば'ddummyy')にdummyが含まれているか検索(/dummy/)した結果、
『含まれていた』=「1」=「真」と判別される。



なるほどねぇ。
こうやって考えると、要素数を取り出す時に
$count = @test ;
で取り出せるっていうのも、ニュアンス的にしっくりくるな〜。



さてさて。
もう一度元に戻ると。


@array = grep( !$count{$_}++, @array ) ;


今は検索とかではなく !$count{$_}++ の真偽を見ている。
さっき分解したとおり、$count{$_}++ は $count{$_} = $count{$_} +1 。
更に、実質比較する内容は $count{$_}  だった。


てことは、
$count{$_}が「1」なら「真」。


ん?忘れ物発見。
「!」があった!!
てことは・・・$count{$_}が「1」以外なら「真」


あー、なるほど!


「!」はぱっと見 $count{$_}++ 全体にかかってるように見えるけれど
実際はgrepの検索条件$count{$_}にかかる意味なのね。
そうすると、


$count{$_}が「1」以外だった場合、
$count{$_} = $count{$_} +1

%countは定義したてのハッシュだから、
$count{$_}が「1」以外
 = $count{$_}という値がまだ無い場合
に相当。


これでやっと納得!!


= = = = = = = = 


長くなったけれど、まとめ・・・


my @array = ('l', 'e', 'i', 'l', 'a');
my %count;
@array = grep( !$count{$_}++, @array ) ;


日本語訳すると、(⇒の先は例)

  • @arrayの要素を1つずつ取り出す。

   ⇒'l'

  • 取り出した要素をキーにした%countの値を確認。

   ⇒$count{'l'}=''(存在しない)

  • その値が「1」以外だったら「真」。

   ⇒存在しない=「1」じゃない=「真」!

  • 真なら@arrayに格納。

   ⇒@array = ('l') という状態になる

  • 真の時は$count{$_}++とする。

   ⇒$count{'l'} = $count{'l'} +1 ・・・もともと空だから$count{'l'}=1

  • @arrayの次の要素で↑の手順を踏む。

   ⇒次の要素は'e'



できたー☆



お1人様1回限りの@array会場イベントで、
初参加する要素クンは、事務処理の最後に
$count{$_}=1
という形で参加済みハッシュ登録されるから、
2回以上参加しようとすると
「お前初めてじゃないな!悪(偽)者めっ!!」
って言われて@array会場から閉め出されちゃうのね。



今日も1つすっきり☆