Perl Perl_0
Perl 「 sort 演算子 」でリストデータの並びをコードポイント順に並び替える (0x2a)
Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x2a 回。
Perl で、リストデータの並びをコードポイント順に並び替える sort 演算子について。「 コードポイント 」順に並び替えられることに注意が必要。
sort 演算子の書式
sort 演算子は、リストデータをコードポイント順に並べてくれる演算子です。僕はそのまま「 ソート 」と読んでいます。
sort 演算子の書式は次の様になります。
sort SUBNAME LIST
sort BLOCK LIST
sort LIST
「 SUBNAME 」はおそらくサブルーチン ( Subroutine ) のことです。
サブルーチンの「 サブ (Sub) 」は、メインルーチンの「 メイン (Main) 」に対するものです。「 ルーチン (Routine) 」は、決まった手順や型にはまった作業を意味します。
Perl における「 サブルーチン 」は、繰り返し利用する処理を、主流になる処理とは別に書いて置くものです。「 ユーザ関数 」ともいわれます。
他のプログラミング言語でも、ほとんど同様の意味で使われる用語です。「 サブルーチン 」についての説明は、別の機会に行います。
「 BLOCK 」は、「 { } 」内に処理を記述したものです。
「 LIST 」は、お馴染みの配列変数やリストリテラル等のリストデータを表します。
リストデータを並べ替える
ここでは、もっともシンプルな書式「 sort LIST 」について確認します。この他の書式は後々理解していきます。
sort 演算子は、受け取ったリストデータを、コードポイント順にソート (並べかえ) します。
コードポイントは、元々 ASCII コードの順番だけを意識すれば良いものだったそうですが、Unicode の導入に伴い、(ASCII コード順は保たれつつも) 例えば、大文字が小文字の前に置かれる等、これまでとは違ったソートが行われる様になっている様です。
次の例では、sort 演算子によって、「 A B C a b c 」とソートされます。
@alphabet = sort qw( C c B b A a ); # A B C a b c
次の例では、「 amuro fraw hayato kai 」の並びになります。
@side7 = sort qw/ kai fraw amuro hayato /; # amuro fraw hayato kai
sort 演算子は、どうやら初めの 1 文字を軸にしてソートしているみたいです。
単純に、次の例ではどうでしょうか。
@alphabet = sort qw/ aac aaa aad aba aab /;
配列 @alphabet には、「 aaa aab aac aad aba 」の並びで格納されます。
1 文字目が同じコードポイント場合は 2 文字目を比較、2 文字目が同じ場合は 3 文字目を ... といった具合にソートしていることが分かります。
数値の場合は、より注意が必要です。
@numerical = sort 99 .. 101;
これは、「 100 101 99 」の並びになります。一般的な日常の意識でいると、「 99 100 101 」の並びが正しい様に思いますが、sort 演算子によるコードポイント順では、それは正しくないのです。
任意の順番にソートする方法もある様ですが、これは別途説明します。つまり僕がまだ理解していないということです。
LIST に配列変数を指定する
sort 演算子の書式にある「 LIST 」には、配列変数を指定することも出来ます。
@side7 = qw/ kai fraw hayato amuro /;
@white = sort @side7; # amuro fraw hayato kai
配列 @white には、ソートされた @side7 のリストデータが格納されます。
また、次の例の様に、ソート元の配列を代入先に指定することも出来ます。
@side7 = qw/ kai fraw hayato amuro /;
@side7 = sort @side7;
LIST を reverse 演算子で操作する
sort 演算子でソートした結果を、reverse 演算子で逆順にすることも出来ます。
@alphabet = qw/ aac aaa aad aba aab /;
@alphabet = reverse sort @alphabet
sort 演算子のみであれば、2 行目の配列 @alphabet は「 aaa aab aac aad aba 」になりましたが、reverse 演算子をはさむことで、「 aba aad aac aab aaa 」の並びにリバースされます。
scalar 演算子を使って、reverse をスカラコンテキストで使ってみます。
@alphabet = qw/ aac aaa aad aba aab /;
@alphabet = scalar reverse sort @alphabet
scalar コンテキストでの reverse は、文字列を連結して 1 文字ずつ逆順にするので、「 aaa aab aac aad aba 」に sort されたリストデータが、「 abadaacaabaaaaa 」とリバースされました。
リストコンテキストの reverse sort では、「 aba aad aac aab aaa 」だったので、スカラコンテキストでは、ソートしたリストデータを連結後に、1 文字ずつリバースしていることが分かります。
数値を数値として並べ替えるメモ
sort 演算子で、数値を並べかえる場合に、思った様に並んでくれないのは、SUBNAME や BLOCK を省略すると、標準で文字列として比較・並び替えが行われるからだそうです。
と、いわれても、数値が数値の通りに並んでくれないのは困るので、ここに sort 演算子による数値の並び替え方法 (昇順/降順) をメモしておきます。
@numerical = 99 .. 101;
@numerical = sort {$a <=> $b} @numerical; # 昇順
@numerical = sort {$b <=> $a} @numerical; # 降順
ここでは、 BLOCK 「 { } 」を利用して、値の比較処理を行っています。「 $a 」と「 $b 」はパッケージのグローバル変数だと言うことです。おそらく、ソート時に値が渡される標準のスカラ変数なんだと思います。
詳細は、「 perldoc.jp - sort 」を参照しましょう。
「 <=> 」は、数値比較演算子で、左右の値の大小関係を比較します。
こちらは、「 Wikibooks - Perl/演算子 」を参照しましょう。
昇順と降順では、スカラ変数 「 $a, $b 」の位置が逆転していることに注目しましょう。つまりそういうことです。
0x2a -> 0x2b へ
参考情報は以下の書籍を中心に Wikipedia および各 Web サイト。それと詳しい先輩。
参考 :「Randal L. Schwartz, brian d foy, Tom Phoenix 共著 近藤 嘉雪 訳「初めての Perl 第 6 版」(オライリー・ジャパン発行 ISBN978-4-87311-567-2)」
次回 (0x2b) へ続く。
過去記事 RSS
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)