ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

PHP, 表データ(連想・多次元配列)をソートする。array_***関数の組み合わせ。

php
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

PHPの2次元配列を使うと、データーベースの表データと同じようにデータを持てます。その配列をソートする方法です。

『DBのSQL使えよ!』って話ですが、PHPだけでも同じようにソートできます。しかし、実用的ではありません。遊びのプログラミングに近い。

サイトにテーブル(表)を表示するとき、ソート機能が必要になることってありますよね?

ただこの場合、まず先に考えるべきなのはDBのSQLを使うことです。

(テーブル操作でDBに勝てるものはない。)

それでダメならJavaScriptを使う。

(サーバーへのアクセス負荷がない。速い。)

今回の話は3番めの候補になるPHPでやってしまう方法です。

多次元配列でよく使う - array_column()

テーブルの情報は二次元配列データです。

(たて(列)とよこ(行)の2つあるから。)

PHPの多次元配列データでは、キーになる一次元の配列を使います。array_column()は多次元配列から一次元配列を取り出す関数です。

(名前のとおりカラム(列)を取り出す。)

成績表テーブルから名前リストを取り出す
<?php

$table = [
    [ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
    [ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
    [ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
    [ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
    [ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
    [ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];

$name = array_column( $table, 'name');
var_export( $name );
result
array (
  0 => '太郎',
  1 => '花子',
  2 => '次郎',
  3 => 'みか',
  4 => 'ジョン',
  5 => 'ステファニー',
)

多次元配列は、[]が何層あるか?で判断します。

テーブルは2層なので2次元配列です。

多次元配列のデータでなにかをするとき、けっこう使うので覚えましょう。

ひとつの項目でソート - array_multisort()

PHPの配列のソートにはarray_multisort()を使います。DBのORDER BYのように複数の条件でソートすることもできます。

まずは、ひとつの条件(列)でソートしてみましょう。

<?php

$table = [
	[ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
	[ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
	[ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
	[ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
	[ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
	[ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];

$score = array_column( $table, 'score' );
array_multisort( $score, SORT_DESC, $table );
var_export( $table );
SORT_ASC昇順
SORT_DESC降順

ソート対象の列の配列をarray_column()で作って、昇順・降順を指定します。

ここではスコアの高い順にソートします。

result
array (
  0 => 
  array (
    'No' => '6',
    'name' => 'ステファニー',
    'score' => '96',
    'sexuality' => '女',
  ),
  1 => 
  array (
    'No' => '2',
    'name' => '花子',
    'score' => '80',
    'sexuality' => '女',
  ),
  2 => 
  array (
    'No' => '4',
    'name' => 'みか',
    'score' => '70',
    'sexuality' => '女',
  ),
  3 => 
  array (
    'No' => '5',
    'name' => 'ジョン',
    'score' => '67',
    'sexuality' => '男',
  ),
  4 => 
  array (
    'No' => '1',
    'name' => '太郎',
    'score' => '56',
    'sexuality' => '男',
  ),
  5 => 
  array (
    'No' => '3',
    'name' => '次郎',
    'score' => '35',
    'sexuality' => '男',
  ),
)

array_multisort()のややこしいところは、関数のリターンは成否(true, false)しか返しません。

パラメータで指定した$tableの値を変更します。元データを変えたくないときは別変数に入れ直してから指定しましょう。

複数の項目でソート - array_multisort()

複数のデータをソートするのはかんたんです。array_multisort()のパラメータを増やします。

性別のスコアの高い順にソートしてみましょう。

性別のスコア順にソート
<?php

$table = [
	[ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
	[ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
	[ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
	[ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
	[ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
	[ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];

$sexuality = array_column( $table, 'sexuality' );
$score = array_column( $table, 'score' );
array_multisort( $sexuality, SORT_DESC, $score, SORT_DESC, $table );
var_export( $table );
result
array (
  0 => 
  array (
    'No' => '5',
    'name' => 'ジョン',
    'score' => '67',
    'sexuality' => '男',
  ),
  1 => 
  array (
    'No' => '1',
    'name' => '太郎',
    'score' => '56',
    'sexuality' => '男',
  ),
  2 => 
  array (
    'No' => '3',
    'name' => '次郎',
    'score' => '35',
    'sexuality' => '男',
  ),
  3 => 
  array (
    'No' => '6',
    'name' => 'ステファニー',
    'score' => '96',
    'sexuality' => '女',
  ),
  4 => 
  array (
    'No' => '2',
    'name' => '花子',
    'score' => '80',
    'sexuality' => '女',
  ),
  5 => 
  array (
    'No' => '4',
    'name' => 'みか',
    'score' => '70',
    'sexuality' => '女',
  ),
)

データベースのORDER BYと同じことができますね?

ただしこの関数は、ORDER BYの条件の数が決まっていないときには使いづらいです。

そこでちょっと工夫します。

サンプル - フレキシブルな条件に対応する

ORDER BYの条件を柔軟に対応する関数を作りました。まずはそれを見てみましょう。

オリジナル・ソート関数 my_sort()
<?php

$table = [
	[ 'No' => '1', 'name' => '太郎', 'score' => '56', 'sexuality' => '男' ],
	[ 'No' => '2', 'name' => '花子', 'score' => '80', 'sexuality' => '女' ],
	[ 'No' => '3', 'name' => '次郎', 'score' => '35', 'sexuality' => '男' ],
	[ 'No' => '4', 'name' => 'みか', 'score' => '70', 'sexuality' => '女' ],
	[ 'No' => '5', 'name' => 'ジョン', 'score' => '67', 'sexuality' => '男' ],
	[ 'No' => '6', 'name' => 'ステファニー', 'score' => '96', 'sexuality' => '女' ],
];

$order_by = [
	[ 'sexuality', SORT_DESC ],
	[ 'score', SORT_DESC ],
];

function my_sort( $table, $order_by ) {
	$args = [];
	
	foreach( $order_by as $tmp ) {
		$args[] = array_column( $table, $tmp[ 0 ] );
		$args[] = $tmp[ 1 ];
	}
	$args[] = &$table;
	$result = call_user_func_array('array_multisort', $args) ? $table : false ;
	return $result;
}

$result = my_sort( $table, $order_by );
var_export( $result );

さっきの性別スコア・ランキングと同じことをしています。ちがいは、$order_byの配列で自由に条件をつけられることだけ。

my_sort()のポイントは、array_multisortのパラメータの数を決めないで実行するためにcall_user_func_array()を使いました。

そしてもうひとつ、結果を受け取る$tableをリファレンス渡しします(&$table)。$argsの中から$tableを抜き出すのが面倒なので。

(C系言語で言えばダブル・ポインタ。)

result
array (
  0 => 
  array (
    'No' => '5',
    'name' => 'ジョン',
    'score' => '67',
    'sexuality' => '男',
  ),
  1 => 
  array (
    'No' => '1',
    'name' => '太郎',
    'score' => '56',
    'sexuality' => '男',
  ),
  2 => 
  array (
    'No' => '3',
    'name' => '次郎',
    'score' => '35',
    'sexuality' => '男',
  ),
  3 => 
  array (
    'No' => '6',
    'name' => 'ステファニー',
    'score' => '96',
    'sexuality' => '女',
  ),
  4 => 
  array (
    'No' => '2',
    'name' => '花子',
    'score' => '80',
    'sexuality' => '女',
  ),
  5 => 
  array (
    'No' => '4',
    'name' => 'みか',
    'score' => '70',
    'sexuality' => '女',
  ),
)

PHPでもかんたんにできますが、僕はDBのSQLでやっちゃったほうがいいかなと思います。

検索して結果をソートとか複合的なことはSQLにかなわないので。

うーん。array_multisort()は、そこまで使う場面があるんだろうか?

前の投稿
PHP, 表データ(連想・多次元配列)を検索する。array_***関数の組み合わせ。
PHP, DateTimeとDateTimeImmutableのちがいと使い分け
次の投稿
コメントを残す

*