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

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

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

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

目次

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

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

解説:初期値など

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

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

  47: //1行に並べる項目数
  48: define('COLS', 5);
  49: 
  50: //列車の系列データ
  51: $TrainType = array(
  52: '103系', '113系', '183系', '201系', '209系', '211系', '485系', '719系',
  53: 'E127系', 'E217系', 'E233系', 'E531系', 'EV-E801系', 'HB-E210系',
  54: 'キハ40形', 'キハ48形', 'キハ52形', 'キハ58形', 'キハ100系', 'キハ110系',
  55: 'キハE120系', 'キハE130系', 'キハE200形',
  56: );

解説:メインプログラム

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

 315: // メイン・プログラム ======================================================
 316: 
 317: //配列をシャフル
 318: shuffle($TrainType);
 319: 
 320: //配列を並べ替え
 321: if (isButton('a')) {
 322:     $mode = '単純ソート';
 323:     sort($TrainType);
 324: else if (isButton('b')) {
 325:     $mode = '辞書ソート';
 326:     usort($TrainType, 'sortTrainType');
 327: else {
 328:     $mode = 'ソートなし';
 329: }
 330: 
 331: //表示
 332: $HtmlBody = makeCommonBody($TrainType, $mode);
 333: echo $HtmlHeader;
 334: echo $HtmlBody;
 335: echo $HtmlFooter;
 336: 
 337: /*

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

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

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

 228: /**
 229:  * 列車系列の大小比較関数(辞書ソート用)
 230:  * @param   string $a, $b 列車の系列
 231:  * @return  int 正:$a > $b,負:$a < $b,0:$a== $b
 232: */
 233: function sortTrainType($a, $b) {
 234:     $pat1 = '/([^0-9]+)([0-9]+)/ui';        //キハxx系
 235:     $pat2 = '/(^[0-9]+)/ui';                //xx系
 236: 
 237:     $ret = 0;
 238:     if (preg_match($pat1, $a, $a2> 0 && preg_match($pat1, $b, $b2&& ($a2[1] == $b2[1])) {
 239:         $ret = (int)$a2[2- (int)$b2[2> 0 ? +1 : -1;
 240:     } else if (preg_match($pat2, $a, $a2> 0 && preg_match($pat2, $b, $b2)) {
 241:         $ret = (int)$a2[1- (int)$b2[1> 0 ? +1 : -1;
 242:     } else {
 243:         $ret = $a > $b ? +1 : -1;
 244:     }
 245:     return $ret;
 246: }

辞書ソートについて

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

参考サイト

(この項おわり)
header