Webリクエストのパラメタを指定したパラメタ名の順でソートするプログラムを書いてみました。
プログラム自体は汎用的なので、パラメタのソートに限らず、それ以外でも利用可能です。
<?php
class ParameterSorter {
private $sortOrder;
// パラメタのソート順を指定
public function __construct($sortOrder) {
$this->sortOrder = array_flip($sortOrder);
$this->max = count($sortOrder);
}
// uksortを使って指定されたパラメタ順でソート
// $sortOrderのキーをパラメタ名に変換して、uksortを使うのは性能を上げるためです。
// ソート順が指定されていないパラメタは、ソート順が指定されたパラメタの後になるように実装しています。
public function sort(&$parameters) {
uksort($parameters, function($a, $b){
return ($this->sortOrder[$a] ?? $this->max) - ($this->sortOrder[$b] ?? $this->max);
});
}
// PHPのuksortは安定でない(同順位の場合もとの順序が保存されない)らしいので、元の順序を確実に保証するバージョンも作成しました。
public function stableSort(&$parameters) {
$originalOrder = array_flip(array_keys($parameters));
uksort($parameters, function($a, $b) use($originalOrder){
$compared = ($this->sortOrder[$a] ?? $this->max) - ($this->sortOrder[$b] ?? $this->max);
if($compared === 0)
{
return $originalOrder[$a] - $originalOrder[$b];
}
return $compared;
});
}
}
下記は使用例になります。
<?php
$sortOrder = ['A', 'B', 'C', 'D', 'E'];
$sorter = new Util\ParameterSorter($sortOrder);
$parameters = [
'Z' => 'z',
'F' => 'f',
'C' => 'c',
'K' => 'k',
'A' => 'a',
'B' => 'b',
];
$sorter->sort($parameters);
print_r($parameters);
$parameters = [
'Z' => 'z',
'F' => 'f',
'C' => 'c',
'K' => 'k',
'A' => 'a',
'B' => 'b',
];
$sorter->stableSort($parameters);
print_r($parameters);
// 下記のような出力結果が得られます。
// サンプルで使ったパラメタ配列では、単純なuksortバージョンと安定バージョンで差は出ませんでした。
// Array
//(
// [A] => a
// [B] => b
// [C] => c
// [Z] => z
// [F] => f
// [K] => k
//)
//Array
//(
// [A] => a
// [B] => b
// [C] => c
// [Z] => z
// [F] => f
// [K] => k
//)
コメント