« 不思議なアリスで悩む | トップページ | Girl Talkで悩む »

2010年5月 3日 (月)

perlのsortで悩む

perlにはsortという関数があって、listをソートできる。

・・・という話の前に、perlの話をしないといけない。これはもう10年以上の付き合いになるスクリプト言語で、つまりプログラミングの話なんです。perlはちょっとエレガントさに欠けるけれども強力な言語で、欠点もあるんだけれどもその特性を活かしてインターネット・サイトでよく使われている。いわゆるCGIの70%位はまだperlじゃないだろうか。

で、仮に作ったテキトーなデータをdataという配列に流しこんでこれをソートしてみる。とかいうマニアックな話なので、今回は御用とお急ぎでない方に限定。

DB<1> @data = (98,9,12,123,456,6);

ソートして、結果をsortedという配列に入れる。

DB<2> @sorted = sort @data;

しかし、結果の中身を見てみると、

DB<3> X sorted
@sorted = (
0 12
1 123
2 456
3 6
4 9
5 98
)

おっと、文字列ソートになってしまった。でも数値ソートを行うことを明示的に示してやると、

DB<4> @sorted=sort {$a<=>$b} @data;

DB<5> X sorted
@sorted = (
0 6
1 9
2 12
3 98
4 123
5 456
)

ちゃんと数値の順にソートされる。

しかし、こんなソートでは役に立たない。ソートしたいのは例えば野球選手名と打率の組みについてソートしたいのだから、単純なリストではなくて、複数の情報を詰め込んだ構造体をその塊ごとソートしたい。

@data = (98,9,12,123,456,6);

こんなふうに配列へ代入できるのだから、

@d[0] = ('ラミレス','(巨)',.322);
@d[1] = ('内川 聖一','(横)',.318);
@d[2] = ('小笠原 道大','(巨)',.309);
@d[3] = ('坂本 勇人','(巨)',.306);
@d[4] = ('井端 弘和','(中)',.306);

これでできるかと思ったのだが、これが何故かできなくて、これが今回の悩みどころ。

$d[0] = \('ラミレス','(巨)',.322);

とか色々やってみたのだけれどもダメで、これはどうも仕様らしい。

5月19日追記:
こうすればできるのだった。

$d[0] = ['ラミレス','(巨)',.322];


しかしこれはこうやって説明するときには便利だけれども、実際のプログラムが動くときにはこんなふうに予めデータを用意できるわけではないので、まぁいいか、と。で、地道にひとつずつ、

DB<6> $d[0][0]='ラミレス'; $d[0][1]='(巨)'; $d[0][2]=.322;
DB<7> $d[1][0]='内川 聖一'; $d[1][1]='(横)'; $d[1][2]=.318;
DB<8> $d[2][0]='小笠原 道大';$d[2][1]='(巨)'; $d[2][2]=.309;
DB<9> $d[3][0]='坂本 勇人'; $d[3][1]='(巨)'; $d[3][2]=.306;
DB<10> $d[4][0]='井端 弘和'; $d[4][1]='(中)'; $d[4][2]=.306;

とやると、

DB<11> X d
@d = (
0 ARRAY(0x28b964)
0 'ラミレス'
1 '(巨)'
2 0.322
1 ARRAY(0x1c9bb14)
0 '内川 聖一'
1 '(横)'
2 0.318
2 ARRAY(0x1d21894)
0 '小笠原 道大'
1 '(巨)'
2 0.309
3 ARRAY(0x1d21984)
0 '坂本 勇人'
1 '(巨)'
2 0.306
4 ARRAY(0x1d219f4)
0 '井端 弘和'
1 '(中)'
2 0.306
)
というふうにちゃんと入る。

さて、これを球団名でソートかけると、

DB<12> @sorted = sort {$$a[1] cmp $$b[1]} @d

DB<13> X sorted
@sorted = (
0 ARRAY(0x1c9bb14)
0 '内川 聖一'
1 '(横)'
2 0.318
1 ARRAY(0x28b964)
0 'ラミレス'
1 '(巨)'
2 0.322
2 ARRAY(0x1d21894)
0 '小笠原 道大'
1 '(巨)'
2 0.309
3 ARRAY(0x1d21984)
0 '坂本 勇人'
1 '(巨)'
2 0.306
4 ARRAY(0x1d219f4)
0 '井端 弘和'
1 '(中)'
2 0.306
)

こういう事ができてくると、perlでよく話題になるマルチ(複数)キー・ソートをやってみたくなる。 これが論理OR演算子を使うと意外に簡単にできて、

DB<14> @sorted = sort {$$a[1] cmp $$b[1] || $$b[2]<=>$$a[2]} @d

同じ球団内では打率の高い人を先に持ってくることができる。

DB<15> X sorted
@sorted = (
0 ARRAY(0x1c9bb14)
0 '内川 聖一'
1 '(横)'
2 0.318
1 ARRAY(0x28b964)
0 'ラミレス'
1 '(巨)'
2 0.322
2 ARRAY(0x1d21894)
0 '小笠原 道大'
1 '(巨)'
2 0.309
3 ARRAY(0x1d21984)
0 '坂本 勇人'
1 '(巨)'
2 0.306
4 ARRAY(0x1d219f4)
0 '井端 弘和'
1 '(中)'
2 0.306
)

ところがこの論理ORを「||」じゃなくて「or」にすると上手くいかないことがあったんだが、これはどう違うんだったっけね? 優先度か?

ちなみに、ここでつかったperlはver 5.10.0のWindows版。

|

« 不思議なアリスで悩む | トップページ | Girl Talkで悩む »

プログラミング」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/214007/48135693

この記事へのトラックバック一覧です: perlのsortで悩む:

« 不思議なアリスで悩む | トップページ | Girl Talkで悩む »