Perlで2次配列をソート関数でソートする
引き続き、Perlでのsort関数での話題です。
2次配列でsort関数を使おうとすると、一気にハイレベルになります。
最初に答えを書いてしまうと、
2次配列 @data があるとして、数値 $data[0][0] と $data[1][0] と $data[2][0] を 昇順にソートします。
@data = sort { @$a[0] <=> @$b[0] } @data;
という式になります。
一見理解できそうですが、よく見るとすごくややこしかったりします。
変数の参照、参照変数の逆参照、無名配列、配列のスライス、というのが理解できていないと理解できません。
まず、$a、$b に何が入っているかというと、
$data[0]、$data[1]、$data[2] のどれかです。
$data[0]には、二次元目の無名配列[0]の参照しているアドレスが入っています。
$data[0][0] は、$data[0]->[0] と同じ意味なので、$data[0]->[0] と考えた方が解りやすいかもしれません。
つまり、$aは二次元目の配列の参照変数なわけです。
それを、@$a として、配列に戻しています。
つまり、$aを$data[0]と考えると、 @{$data[0]} と逆参照したことになります。
@$a[0]の [0]の部分ですが、これは配列の要素を表しているのではありません。
配列 @$a の中から要素0をスライスしています。
スライスの簡単な例として、現在の日付を取得する方法があります。
普通は、
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime( $time );
として現在の日時すべてを取得しますが、
($mday, $mon, $year) = (localtime( $time ))[3,4,5];
とすれば、余分な変数が要りません。
つまり、@$a[0]の [0]の部分では、
配列の中から要素0のみを取り出して配列を返しています。
結果的に返された配列が1つだけなので、要素0の値のみが返って来ます。
よって、$a が$data[0] だった場合、$data[0][0] の値が取り出せることになります。
2次配列をソートできるようになると、
$data[0][0] = 20; $data[0][1] = "山田";
$data[1][0] = 15; $data[1][1] = "田中";
$data[2][0] = 30; $data[2][1] = "佐藤";
といったデータを、数値順に名前を取り出せます。
たとえば、
@data = sort { @$a[0] <=> @$b[0] } @data;
$data[0][0] = 15; $data[0][1] = "田中";
$data[1][0] = 20; $data[1][1] = "山田";
$data[2][0] = 30; $data[2][1] = "佐藤";
にソートされます。
2006/11/08 追記
なんかここを見てくださっている方もいらっしゃるようなので、追記です。
上の方法でもソートできますが、配列の逆参照なんて使わなくてもできます。(汗)
上の例だと、
@data = sort { $a->[0] <=> $b->[0] } @data;
でOKです。
$a と $b は
$data[0]~$data[2]のことだから、2次元目の[0]は
$a->[0]、$b->[0] で取れますよね。
| 固定リンク
| コメント (0)
| トラックバック (0)
最近のコメント