はじめに
PHPで配列をソートしたいとき、sort() や asort() などの組み込み関数を使うことが多いと思います。
一方で、
- 独自のルールで並び替えたい
- 複数条件でソートしたい
といったケースでは usort() を使う場面が出てきます。
本記事では、usort() と 宇宙船演算子(<=>) を組み合わせた、
ソート実装について紹介します。
usortとは何か
usort() は、ユーザー定義の比較関数を使って配列をソートする関数です。
usort(array &$array, callable $callback): bool
$numbers = [5, 1, 10, 3];
usort($numbers, function ($a, $b) {
if ($a === $b) {
return 0;
}
return $a < $b ? -1 : 1;
});
// 結果: [1, 3, 5, 10]
比較関数は、次のルールで値を返します。
- 負の値:callbackの第1引数が小さい($a を $b より前に並べる)
- 0:callbackの引数同志が等しい(順番の並び順を変更しない)
- 正の値:callbackの第1引数が大きい($a を $b より後ろに並べる)
この「数値を返す」という仕様が、宇宙船演算子と非常に相性が良いポイントです。
宇宙船演算子(<=>)とは
宇宙船演算子(spaceship operator)は、PHP 7 から導入された比較演算子です。
$a <=> $b
$a = 10;
$b = 5;
$a <=> $b; // 1
評価結果は以下の通りです。
-
$a < $bの場合:-1 -
$a == $bの場合:0 -
$a > $bの場合:1
つまり、usort() が要求する返り値をそのまま返してくれる演算子です。
usortと宇宙船演算子の組み合わせ
まずはシンプルな例です。
$numbers = [10, 3, 7, 1];
usort($numbers, function ($a, $b) {
return $a <=> $b;
});
// [1, 3, 7, 10]
昇順・降順の切り替えも簡単です。
// 降順
usort($numbers, fn ($a, $b) => $b <=> $a);
連想配列(配列の配列)をソートする
実務でよくあるのが、次のようなデータです。
$users = [
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 20],
['name' => 'Chris', 'age' => 25],
];
ageで昇順ソート
usort($users, fn ($a, $b) => $a['age'] <=> $b['age']);
nameで降順ソート
usort($users, fn ($a, $b) => $b['name'] <=> $a['name']);
コード量が少なく、比較条件が一目で分かるのがメリットです。
複数条件でソートする
「まずageで昇順、同じならnameで昇順」といったケースもよくあります。
usort($users, function ($a, $b) {
return $a['age'] <=> $b['age']
?: $a['name'] <=> $b['name'];
});
- 最初の比較結果が
0の場合のみ次の条件へ -
?:を使うことで簡潔に書ける
複数条件でも可読性を保ちやすい書き方です。
オブジェクト配列をソートする
EloquentモデルやDTOなど、オブジェクト配列にもそのまま使えます。
usort($users, fn ($a, $b) => $a->age <=> $b->age);
プロパティアクセスに変わるだけで、考え方は同じです。
注意点
型の違いに注意
宇宙船演算子は型も考慮して比較します。
'10' <=> 2 // 1
意図しない結果にならないよう、
事前に型を揃えておくと安全です。
まとめ
usort() と宇宙船演算子を組み合わせることで、
- 比較関数が短く書ける
- 条件が読みやすい
- 複数条件ソートも自然に表現できる
といったメリットがあります。
「比較関数がごちゃごちゃしてきた」と感じたら、
宇宙船演算子を使った書き方を検討してみると、
コードがかなりスッキリします。