PHPで列車の系列をソートする

(1/1)
ぱふぅ家のホームページ乗り物大図鑑では、列車の型式をリンク見出しにしている。103系,105系,107系‥‥と列車の系列が小さい順に並んでいくが、キハ100系,キハ110系,キハ40形,キハ48形‥‥のように、冒頭が数字でないと順番が混乱してしまう。
そこで今回は、辞書ソートを使って、「キハ40形,キハ48形,キハ100系,キハ110系」と正しく並べ替えるようにするPHPプログラムを作ってみることにする。

サンプル・プログラムの実行例

PHPで列車の系列をソートする

目次

サンプル・プログラムのダウンロード

圧縮ファイルの内容
sortTrainType.phpサンプル・プログラム本体

解説:初期値など

初期値などは、あらかじめ定数で定義しておく。
変更不可となっている定数以外は、自由に変更できる。

列車の系列データは、配列 $TrainType にあらかじめ代入しておく。

0047: //1行に並べる項目数
0048: define('COLS', 5);
0049: 
0050: //列車の系列データ
0051: $TrainType = array(
0052: '103系', '113系', '183系', '201系', '209系', '211系', '485系', '719系',
0053: 'E127系', 'E217系', 'E233系', 'E531系', 'EV-E801系', 'HB-E210系',
0054: 'キハ40形', 'キハ48形', 'キハ52形', 'キハ58形', 'キハ100系', 'キハ110系',
0055: 'キハE120系', 'キハE130系', 'キハE200形',
0056: );

解説:メインプログラム

メインプログラムでは、まず配列 $TrainType をシャフルする。
続いて、クリックしたボタンに応じて、単純ソートするか、辞書ソートするかを決める。単純ソートは、組み込み関数  sort  を使って処理する。
辞書ソートは、比較のためのユーザー関数 sortTrainType と組み込み関数  usort  を使って処理する。

0315: // メイン・プログラム ======================================================
0316: 
0317: //配列をシャフル
0318: shuffle($TrainType);
0319: 
0320: //配列を並べ替え
0321: if (isButton('a')) {
0322:     $mode = '単純ソート';
0323:     sort($TrainType);
0324: else if (isButton('b')) {
0325:     $mode = '辞書ソート';
0326:     usort($TrainType, 'sortTrainType');
0327: else {
0328:     $mode = 'ソートなし';
0329: }
0330: 
0331: //表示
0332: $HtmlBody = makeCommonBody($TrainType$mode);
0333: echo $HtmlHeader;
0334: echo $HtmlBody;
0335: echo $HtmlFooter;
0336: 
0337: /*

解説:列車系列の大小比較関数(辞書ソート用)

ユーザー関数 sortTrainType は、渡された2つの列車系列の大小関係を返す。

ロジックは次の通り――。
  1. 系列が「数字以外+数字」の組み合わせで、かつ数字以外の部分が等しいなら、数字の大小比較をする。
  2. 系列が数字で始まるなら、数字の大小比較をする。
  3. 系列がそれ以外なら、全体を文字列として大小比較する。

0228: /**
0229:  * 列車系列の大小比較関数(辞書ソート用)
0230:  * @param   string $a, $b 列車の系列
0231:  * @return  int 正:$a > $b,負:$a < $b,0:$a== $b
0232: */
0233: function sortTrainType($a$b) {
0234:     $pat1 = '/([^0-9]+)([0-9]+)/ui';        //キハxx
0235:     $pat2 = '/(^[0-9]+)/ui';                //xx
0236: 
0237:     $ret = 0;
0238:     if (preg_match($pat1$a$a2) > 0 && preg_match($pat1$b$b2) && ($a2[1] == $b2[1])) {
0239:         $ret = (int)$a2[2] - (int)$b2[2] > 0 ? +1 : -1;
0240:     } else if (preg_match($pat2$a$a2) > 0 && preg_match($pat2$b$b2)) {
0241:         $ret = (int)$a2[1] - (int)$b2[1] > 0 ? +1 : -1;
0242:     } else {
0243:         $ret = $a > $b ? +1 : -1;
0244:     }
0245:     return $ret;
0246: }

辞書ソートについて

このように辞書ソートは、ソート対象によって大小比較関数を用意する必要がある。

参考サイト

(この項おわり)
header