EPoch Official Blog

自費訪問リハビリサービス、セラピスト向けセミナー、訪問看護ステーション、IT事業、Body +、スポーツ事業など幅広く事業展開しています。

PHP7 による多次元連想配列のソートの糖衣構文

たまにはプログラムの話をしてみます。
仰々しいタイトルがついていて、
何のことやらさっぱり分かりませんが、
糖衣構文 (Syntactic Sugar) というのは、
書き方がシンプルになる新しい構文のことです。

糖衣構文がどんなものか、
下記の例を見てみましょう。

◆ 通常構文
if (isset($_GET['keyword'])) {
$keyword = $_GET['keyword'];
} else {
$keyword = 'no word';
}

三項演算子を使った糖衣構文 (PHP5.3 以前)
$keyword = isset($_GET['keyword']) ? $_GET['keyword'] : 'no word';

エルビス演算子を使った糖衣構文 (PHP5.3 以降)
$keyword = @$_GET['keyword'] ?: 'no word';

◆ Null合体演算子を使った糖衣構文 (PHP 7 以降)
$keyword = $_GET['keyword'] ?? 'no word';


このように簡略化した書き方が出来るので、
きちんと使えばすっきりした記述になりますが、
無計画に使ってしまうと、省略されすぎたために
分かりにくくなる場合もあります。

 

さて、本題に入ります。

例) データベースから取得してきたゆるキャラ名簿リストから、
都道府県別のランキングを作りたい、とします。

都道府県の ID 順に並べ、
同じ都道府県の中では得票数順に並べ、
得票数も同じ場合は五十音順に並べる、
という操作をしなければなりません。

このような操作はあまり珍しい話でもありません。


本来なら MySQL 側で取得する段階で、
ORDER BY を行うのが常套手段ですが、
諸事情により PHP 側でソートを行わなければならないとしたら、
さて、どのように実装するべきでしょうか。

 

◆ データベースから取得してきたゆるキャラ名簿
$data = array(
array(
'id' => 1,
'name' => 'しんじょう君',
'ruby' => 'しんじょうくん',
'prefecture' => '39:高知県',
'vote' => 2500
),
array(
'id' => 2,
'name' => 'はにぽん',
'ruby' => 'はにぽん',
'prefecture' => '11:埼玉県',
'vote' => 2200
),
array(
'id' => 3,
'name' => 'チュッピー',
'ruby' => 'ちゅっぴい',
'prefecture' => '33:岡山県',
'vote' => 2100
)
);

 

色々な方法はありますが、
通常構文の中で言えば、
array_multisort を使うのが最適です。

◆ 多次元連想配列ソートの通常構文
$prefecture = array();
$vote = array();
$ruby = array();
foreach ($data as $index => $row) {
$prefecture[$index] = $row['prefecture'];
$vote[$index] = $row['vote'];
$ruby[$index] = $row['ruby'];
}

array_multisort($prefecture, SORT_ASC, $vote, SORT_DESC, $ruby, SORT_ASC, $data);

 

さて、これを PHP 7 の糖衣構文で書くと
どのようになるでしょうか。

array_multisort ではなく、usort を使い、
宇宙船演算子 <=> とエルビス演算子 ?: と
無名関数 (クロージャ) を利用します。

PHP 7 以降の多次元連想配列ソートの糖衣構文
usort($data, function($a, $b) {
return $a['prefecture'] <=> $b['prefecture']
?: $b['vote'] <=> $a['vote']
?: $a['ruby'] <=> $b['ruby']
});

 

10 行あったプログラムが半分の 5 行になりました。
と、いう部分は実はあまり問題ではなく、
下記のような点が重要です。

・無駄な変数を宣言しなくてよくなった。
・array_multisort に 7 つも引数を渡すのが分かりにくい。
・array_multisort の引数のルールも厄介。
・ソート条件の応用がしやすい。

 

ちなみに、糖衣構文とは逆の、
余計に読みにくくなる書き方をすることを、
構文塩 (Syntactic Salt) といいます。
この塩分が過剰に含まれていると、
リアルにプログラマの血圧が上昇すると言われています…。
http://catb.org/jargon/html/S/syntactic-salt.html

 

このように新しいサーバ環境と新しい PHP
使えるようにしておくことで、
プログラムの柔軟性と堅牢性を両立しやすくなります。

PHP 7 のサーバを使いたい方は
ぜひご相談ください。

it.ep-och.com