PHP で配列を並び替えたいとき、まず使い方を覚えておきたいのが sort() をはじめとする組み込みのソート関数です。値の昇順・降順、キーでの並び替え、並べ替えてもキーを保つかどうかといった目的に応じて、sort / rsort / asort / arsort / ksort / krsort が用意されています。この記事では、これら6つの基本関数の違いと使い方を、実際の出力を添えたコードで解説します。どれも名前のルールが共通しているので、対応関係をつかめば迷わず選べるようになります。
目次
配列の並び替えと、関数名のルール
PHP の配列は「キーと値のペア」が並んだものです。並び替えでは「値を基準に並べるのか、キーを基準に並べるのか」「昇順か降順か」「並べ替えたあとキーをそのまま保つか、振り直すか」という3つの観点があります。基本のソート関数は、この観点を関数名の組み合わせで表しています。
名前の付き方には規則があります。先頭の a は連想配列(associative)でキーを保つこと、k はキー(key)で並べること、r は逆順(reverse/降順)を表します。たとえば arsort は「a(キー保持)+ r(降順)+ sort」、krsort は「k(キー基準)+ r(降順)+ sort」と読み解けます。このルールを知っておくと、6つの関数を丸暗記しなくても役割を思い出せます。
| 関数 | 並べる基準 | 順序 | キーの扱い |
|---|---|---|---|
sort() | 値 | 昇順 | 0 から振り直す |
rsort() | 値 | 降順 | 0 から振り直す |
asort() | 値 | 昇順 | キーを保持する |
arsort() | 値 | 降順 | キーを保持する |
ksort() | キー | 昇順 | キーを保持する |
krsort() | キー | 降順 | キーを保持する |
これらはいずれも、決まったルール(値の大小・キーの大小)で並べる関数です。「日付順」「特定の項目を基準に」といった自由な条件で並べたいときは、比較のしかたを自分で書ける usort() 系の関数を使いますが、この記事では組み込みの基本関数に絞って見ていきます。
sort と rsort で値を並べ替える
もっとも基本的なのが sort() です。配列の値を昇順(小さい順)に並べ替えます。降順(大きい順)にしたいときは rsort() を使います。
<?php
$numbers = [3, 1, 4, 1, 5, 2];
sort($numbers); // 昇順に並べ替える
print_r($numbers);
// Array
// (
// [0] => 1
// [1] => 1
// [2] => 2
// [3] => 3
// [4] => 4
// [5] => 5
// )
rsort($numbers); // 降順に並べ替える
print_r($numbers);
// Array
// (
// [0] => 5
// [1] => 4
// [2] => 3
// [3] => 2
// [4] => 1
// [5] => 1
// )
ここで重要なのは、これらの関数が元の配列そのものを直接書き換えるという点です。引数 $numbers は参照で渡されるため、関数を呼んだあとの $numbers がそのまま並べ替え後の配列になります。そして戻り値は並べ替えた配列ではなく、成功したかどうかを表す真偽値(true / false)です。この性質は紹介する6つの関数すべてに共通します。「並べ替えた結果は引数の配列に入る」「戻り値は成否」と覚えておきましょう。
また sort() と rsort() は並べ替えのあとにキーを 0 から振り直します。上の例のように添字配列ならそのまま 0 始まりの連番になりますが、連想配列に使うとキーが失われるため注意が必要です(後述します)。
asort と arsort で値順に並べてキーを残す
「キーと値の対応を保ったまま、値で並べ替えたい」というときに使うのが asort()(昇順)と arsort()(降順)です。並べ替えても元のキーがそのまま付いてくるので、連想配列の並び替えに向いています。
<?php
$scores = [
'tanaka' => 80,
'suzuki' => 95,
'sato' => 70,
];
asort($scores); // 値(点数)の昇順。キーは保持
print_r($scores);
// Array
// (
// [sato] => 70
// [tanaka] => 80
// [suzuki] => 95
// )
arsort($scores); // 値の降順。キーは保持
print_r($scores);
// Array
// (
// [suzuki] => 95
// [tanaka] => 80
// [sato] => 70
// )
点数の順に並べ替えても、誰の点数かを示すキー(名前)が値とセットで移動しているのが分かります。スコアのランキングや、商品名と価格のような「名前付きデータ」を値順に並べたいときに役立ちます。
ksort と krsort でキー順に並べる
値ではなくキーを基準に並べ替えたいときは ksort()(キーの昇順)と krsort()(キーの降順)を使います。こちらも値とキーの対応はそのまま保たれます。
<?php
$fruits = [
'banana' => 3,
'apple' => 1,
'cherry' => 2,
];
ksort($fruits); // キー(果物名)のアルファベット昇順
print_r($fruits);
// Array
// (
// [apple] => 1
// [banana] => 3
// [cherry] => 2
// )
krsort($fruits); // キーの降順
print_r($fruits);
// Array
// (
// [cherry] => 2
// [banana] => 3
// [apple] => 1
// )
キーが文字列ならアルファベット順、数値ならその大小で並びます。連想配列をキー名でそろえて表示したいときや、年・月をキーにしたデータを時系列に並べたいときに便利です。
連想配列に sort を使うとキーが消える
つまずきやすいのが、連想配列に sort() や rsort() を使ってしまうケースです。これらの関数はキーを 0 から振り直すため、せっかくのキー(名前)が失われ、ただの 0 始まりの添字配列になってしまいます。
<?php
$scores = [
'tanaka' => 80,
'suzuki' => 95,
'sato' => 70,
];
sort($scores); // 連想配列に sort を使うと…
print_r($scores);
// Array
// (
// [0] => 70 // 名前のキーが消えて
// [1] => 80 // 0 からの連番に振り直される
// [2] => 95
// )
値の並び自体は正しく昇順になっていますが、「誰の点数か」という情報が消えてしまいました。連想配列を値で並べてキーも残したいなら sort() ではなく asort() / arsort() を、キーで並べたいなら ksort() / krsort() を選びます。キーを保ちたいかどうかで、頭に a や k が付く関数を使い分けるのがポイントです。
戻り値を変数に代入してしまう間違い
もう一つよくあるのが、戻り値を並べ替え後の配列だと思って代入してしまうミスです。前述のとおり、これらの関数の戻り値は成否を表す真偽値です。次のように書くと、$sorted には配列ではなく true が入ってしまいます。
<?php
$numbers = [3, 1, 2];
// 間違い:戻り値(true)を代入してしまう
$sorted = sort($numbers);
var_dump($sorted);
// bool(true) ← 配列ではない!
// 正しい:並べ替え結果は元の $numbers に入っている
sort($numbers);
print_r($numbers);
// Array
// (
// [0] => 1
// [1] => 2
// [2] => 3
// )
JavaScript の Array.prototype.sort() のように「並べ替えた配列が返ってくる」言語に慣れていると、つい $sorted = sort(...) と書きたくなりますが、PHP の挙動は異なります。並べ替えの結果は引数に渡した配列そのものに反映される、と覚えておきましょう。元の配列を残したい場合は、$copy = $numbers; のように先に複製してから複製側を並べ替えます。
文字列の数字を自然な順番で並べる
sort() は標準では文字列を1文字ずつ比較します。そのため "img10" と "img2" のような文字列を並べると、"img10" が "img2" より前に来てしまい、人間が期待する番号順にはなりません。これを直すには、第2引数に並べ替え方法を指定するフラグを渡すか、自然順で並べる専用関数を使います。
<?php
$files = ['img10', 'img2', 'img1'];
// 通常の sort では文字列として比較され、期待どおりにならない
sort($files);
print_r($files);
// Array
// (
// [0] => img1
// [1] => img10 // 10 が 2 より前に来てしまう
// [2] => img2
// )
// SORT_NATURAL フラグで「自然順」に並べ替える
$files = ['img10', 'img2', 'img1'];
sort($files, SORT_NATURAL);
print_r($files);
// Array
// (
// [0] => img1
// [1] => img2
// [2] => img10 // 番号順に並ぶ
// )
SORT_NATURAL は、文字列の中の数字を数値としてまとめて比較する指定です。同じことをキーを保ったまま行いたいときは、専用関数の natsort() が使えます(natsort() は asort() のように元のキーを保持します)。ファイル名や型番のように数字混じりの文字列を扱うときは、こうした自然順の並べ替えを検討してください。
まとめ
PHP の基本ソート関数は、関数名の組み合わせで「何を基準に・どの順序で・キーをどう扱うか」を表しています。要点を振り返ります。
sort/rsortは値を昇順・降順に並べ、キーを 0 から振り直すasort/arsortは値で並べてキーを保持する(連想配列向き)ksort/krsortはキーを基準に並べる- これらは元の配列を直接書き換え、戻り値は成否の真偽値(並べ替え後の配列ではない)
- 連想配列に
sortを使うとキーが消えるのでasort系・ksort系を使う - 数字混じりの文字列は
SORT_NATURALやnatsort()で自然順に並べられる
名前の a(キー保持)・k(キー基準)・r(降順)というルールさえ押さえておけば、6つの関数を迷わず使い分けられます。決まったルールではなく独自の条件で並べたくなったら、比較関数を自分で書ける usort() 系に進むとよいでしょう。