Theme
SD MILIEU

2017-5-11

[PHP]usortに関する覚書

PHP でソートをしたくなって、usort って関数がすごく便利で良かったんだけど正直理解しづらい部分があって未来の自分がすぐ使い方を思い出せるようにするための覚書。

PHP: usort - Manual

使い方

usort($array, function($a, $b) {
  // 返り値が正なら$bが手前、負なら$aが手前にくるべきやつと判断される
  return $a - $b;
});

上記のように、第一引数にはソートしたい配列、第二引数には値の比較用の関数を渡す。

比較用の関数に関して、コメントに書いている通り返り値が正なら二つ目の引数である$b、負の値なら一つ目の引数である$a が配列の手前にくるべきやつであると判断される。

もう一度書く、「返り値が正なら第二引数が手前、負なら第一引数が手前」である。

例 1

数値が格納されているインデックス配列を昇順に並び替えたい場合は以下の通りになる。

$array = [1, 3, 6, 3, 4, 2];

usort($array, function($a, $b) {
  return $a - $b;
});

var_dump($array);

出力結果は

array(6) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(3)
  [4]=>
  int(4)
  [5]=>
  int(6)
}

「$a - $b」が正になるのは$a が$bより大きい場合、つまり昇順に並べ替えたいので$b が手前に来て欲しいパターンなので、「返り値が正なら第二引数が手前、負なら第一引数が手前」より$b が手前に来る。

例 2

例 1 のような単純なパターンなら usort の恩恵はほとんど感じられないが、オブジェクトや多次元配列なんかをソートしたい際はすごく重宝する。例 2 はそんなパターン

名簿を格納している配列$people が存在しており、その配列を「親、教師、学生」の順で並び替えしたいといった場合は以下のようなコードになる。

$people = [
  [
    "name" => "まさし",
    "type" => "student",
  ],
  [
    "name" => "たかし",
    "type" => "teacher"
  ],
  [
    "name" => "はなこ",
    "type" => "parent"
  ],
  [
    "name" => "さなえ",
    "type" => "student"
  ]
];

usort($people, function($a, $b) {
  $order = [
    "parent",
    "teacher",
    "student"
  ];

  $aOrder = array_search($a["type"], $order);
  $bOrder = array_search($b["type"], $order);

  return $aOrder - $bOrder;
});

var_dump($people);

出力結果は

array(4) {
  [0]=>
  array(2) {
    ["name"]=>
    string(9) "はなこ"
    ["type"]=>
    string(6) "parent"
  }
  [1]=>
  array(2) {
    ["name"]=>
    string(9) "たかし"
    ["type"]=>
    string(7) "teacher"
  }
  [2]=>
  array(2) {
    ["name"]=>
    string(9) "さなえ"
    ["type"]=>
    string(7) "student"
  }
  [3]=>
  array(2) {
    ["name"]=>
    string(9) "まさし"
    ["type"]=>
    string(7) "student"
  }
}

このように、オブジェクトの配列や多次元配列をソートしたい際に、usort だとややこしい部分はあるものの比較的シンプルにソート処理を書くことが出来る。