スキップしてメイン コンテンツに移動

Webのリクエストのパラメタを指定したパラメタ順でソートする方法(PHP)

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
//)

コメント