blog20100901

2013/08/20 - プログラミング言語 Perl にまつわる etc. - Perl monger
参考 : perldoc, perldoc.jp, search.cpan.org, perldoc.perl.org ...
「 初めての Perl 第 6 版 」(オライリー・ジャパン発行 ISBN978-4-87311-567-2) 」
「 続・初めての Perl 改訂版 」(オライリー・ジャパン発行 ISBN4-87311-305-9) 」
「 Effective Perl 第 2 版 」(翔泳社発行 ISBN978-4-7981-3981-4) 」 ... etc,.

Perl Perl_4

Perl ソート再び 数値順 sort, スペースシップ演算子 (0x24a)

Perl ソート再び 数値順 sort, スペースシップ演算子 (0x24a)

目次 - Perl Index



Theme



Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x24a 回。

Perl で、リストデータを「 ソート 」( 分類する, 整列させる ) する演算子「 sort 」を改めて確認する。この Perl の「 sort 」については (0x2a) で一度確認しています。


sort の書式



まずはじめに、改めて演算子「 sort 」の書式を確認しておきます。


sort SUBNAME LIST
sort BLOCK LIST
sort LIST



この書式の内、(0x2a) で確認をしたのは 3 番目の「 sort LIST 」の動作のみでした。


コードポイント順



最もシンプルな書式「 sort LIST 」を利用する場合、演算子「 sort 」は、「 LIST 」を「 コードポイント順 」、つまり、文字列比較でソートします。


my @chr = sort qw/ C A E B D /;

# A B C D E
print "@chr\n";



これは、簡素で便利ですが、数値をソートする場合には、おそらく意図していない並べ替えを行います。


my @num = sort qw/ 99 98 101 100 /;

# 100 101 98 99
print "@num\n";



(0x2a) では、適切に数値をソートする演算子「 <=> 」( スペースシップ演算子 ) を少しだけ確認しました。

「 <=> 」を使うには、「 sort BLOCK LIST 」の書式を使います。


my @num = sort { $a <=> $b } qw/ 99 98 101 100 /;

# 98 99 100 101
print "@num\n";



スカラ変数「 $a 」と「 $b 」は、Perl で予め予約された特別な変数です。ですから、通常プログラム内で任意に利用することは出来ません。詳細は perlvar - perldoc.jpsort - perldoc.jp を確認してみてください。

今回は、数値を並べ替える際の「 sort 」の動作を確認してみます。


並べ方を伝えるためのサブルーチン



書式にある「 sort SUBNAME LIST 」は、サブルーチン「 SUBNAME 」を引数として「 sort 」に渡す形式です。

通常「 サブルーチン 」は、 (0x2f) 等で確認したように、「 特定の処理をするためのひとかたまりのコード 」で、ユーザが定義した関数のことを意味します ( 少なくとも Perl では )。

「 sort 」に渡すサブルーチンも同様に、ひとかたまりの処理をまとめたものですが、それは「 sort 」( Perl ) に並べ方を伝えるための「 sort-definition subroutine 」( ソート定義サブルーチン ) である必要があります。

実のところ、前述したスペースシップ演算子「 <=> 」は、数値を正しく並べるソート定義サブルーチンのショートカットのようなものだと理解しています。


数値を並べ替えるサブルーチン



リストされたデータは、常に 2 つの値で比較されます。このため、「 sort 」は 2 つの値の入れ物としてスカラ変数「 $a 」と「 $b 」を予め持っています。

それから、「 sort 」は「 $a を $ b より前に置く 」場合の値、「 $a を $b より後ろに置く 」場合の値、「 $a と $b に順番を付けられない 」場合の 3 つの値を受け取ります。

この 3 つの値は次のように「 -1 」「 0 」「 1 」の数値で表されます。


$a を $b より前に置く -1
$a と $b に順番をつけられない 0
$a を $b より後に置く 1



「 sort 」のためのソート定義サブルーチンは、この 3 つの値を適切に返す処理を定義するだけ構いません。あとは「 sort 」( と Perl ) がよしなに並べ替えを行ってくれます。

例えば、数値を昇順 (小さい順) で並べるには、次の様なソート定義サブルーチンを書くことが出来ます。


sub by_number {
if ($a < $b) { -1 } elsif ($a > $b) { 1 } else { 0 }
}



このプログラムは、まず、「 $a が $b より小さい 」場合に「 -1 」を返して「 $a 」を「 $b 」より前に置きます。

もし、「 $a が $b より大きい 」場合は「 1 」を返して「 $a 」を「 $b 」より後ろに置きます。

「 $a が $b より大きくも小さくもない 」場合は、順番を付けられないので「 0 」を返します。

このソート定義サブルーチンを「 sort 」の引数として指定してあげれば、適切にソートされた数値を得ることが出来ます。


my @numbers = qw/ 111 98 99 100 101 /;

# サブルーチン by_number を指定する
my @result = sort by_number @numbers;

# 数値が昇順で正しく並ぶ
# 98 99 100 101 111
print "@result\n";



なお、ソート定義サブルーチンを「 sort 」に指定する場合は、サブルーチンを表すシジル「 & 」は付けません。

また、サブルーチンの名前「 SUBNAME 」は、スカラ変数に格納した文字列でも利用可能です。


my $subname = 'by_number';

# SUBNAME にスカラ変数を指定
my @num = sort $subname qw/ 99 98 101 100 /;



なんだか便利そうですね。


「 <=> 」とサブルーチン



前項のソート定義サブルーチンは、スペースシップ演算子「 <=> 」を利用した次の記述と同じ動作をします。


my @result = sort { $a <=> $b } @numbers;



数値を「 降順 」で並べたい場合は、次のように「 $a 」と「 $b 」の位置を入れ替えれば済みます。


my @result = sort { $b <=> $a } @numbers;



これは、前項のソート定義サブルーチンでも同じことで、「 $a 」と「 $b 」の位置を入れ替えれば降順で並べることが出来ます。


sub by_number {
if ($b < $a) { -1 } elsif ($b > $a) { 1 } else { 0 }
}



そうといっても、サブルーチンの定義や「 $a 」と「 $b 」の入れ替えの手間を考えると、数値の並べ替えは、素直にスペースシップ演算子「 <=> 」を使った方が良さそうです。


0x24a -> 0x24b へ



次回は、スペースシップ演算子と同じく 3 文字の名前をもつソートのための演算子「 cmp 」を確認します。


参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。

目次 - Perl Index




















同じカテゴリー(Perl)の記事
 Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228) (2023-10-11 23:49)
 Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227) (2023-05-26 15:41)
 Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226) (2023-05-19 17:05)
 Perl mp2 翻訳 テンプレートシステムの選択 (d225) (2022-08-15 22:23)
 Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224) (2022-06-15 20:43)
 Perl mp2 翻訳 チュートリアル (d223) (2022-06-15 20:42)
上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

Llama
リャマ
TI-DA
てぃーだブログ
プロフィール
セラ (perlackline)
セラ (perlackline)
QRコード
QRCODE
オーナーへメッセージ

PAGE TOP ▲