[PHP]2次元配列、多次元配列のソート

Read More

PHPで2次元配列(或いは多次元配列)のソートをする方法。


最初に結論を書くとPHP関数のarray_multisort()ってのを使えばわりと簡単に実装できる。
■PHP: array_multisort - Manual
http://php.net/manual/ja/function.array-multisort.php

array_multisort()を使うと自前でごにょごにょやるより断然シンプルに書けるうえ、
SQLのORDER BY句と同様にソートの条件を複数指定することができる。

この、「ソートの条件を複数指摘できる」ってのがとにかく大きい。



--
まずサンプルデータを準備する。


ここではDBのレコードの典型的な形式を元に説明をしていく。
以下のようなレコードがあるものとする。

■DBレコードのデータ例
volume | edition
-------+--------
    67 |       2
    86 |       1
    85 |       6
    98 |       2
    86 |       6
    67 |       7


これを以下のように$dataの配列に格納したものとする。

■配列に格納
<?php
$data[] = array('volume' => 67, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 1);
$data[] = array('volume' => 85, 'edition' => 6);
$data[] = array('volume' => 98, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 6);
$data[] = array('volume' => 67, 'edition' => 7);
?>


これでデータの準備完了。


--
ではvolumeという列名のものをソートしてみる。


■2次元配列のソート:array_multisort()を利用したもの
<?php
foreach($data as $key => $row) {
  $volume[$key]  = $row['volume'];
}// end foreach
array_multisort($volume, SORT_DESC, $data);
print_r($data);
?>


■実行結果
> array (
  0 => array (
    'volume' => 98,
    'edition' => 2,
  ),
  1 => array (
    'volume' => 86,
    'edition' => 1,
  ),
  2 => array (
    'volume' => 86,
    'edition' => 6,
  ),
  3 => array (
    'volume' => 85,
    'edition' => 6,
  ),
  4 => array (
    'volume' => 67,
    'edition' => 2,
  ),
  5 => array (
    'volume' => 67,
    'edition' => 7,
  ),
)



オー!すごい!!

今日までarray_multisort()って使えない関数の一つだとばっかり思ってた。

正直スマンカッタ



というかarray_multisort()って「複数の配列を同時にソートする関数」くらいにしか認識していなかった。

こんな使い方ができるなんてな。



ちなみにこのarray_multisort()を知る前は自前で組んでいた。
以下は先述したデータと同じものを使って組んだ並び替え。

■2次元配列のソート:自前で適当に組んだもの
<?php
foreach($data as $key => $row) {
	$volume[$key]  = $row['volume'];
}// end foreach
arsort($volume);
foreach($volume as $key => $val) {
	$volume[$key] = $data[$key];
}// end foreach
$data=array_merge($volume, array());
print_r($data);
?>


■実行結果
<?php
array (
  0 => array (
    'volume' => 98,
    'edition' => 2,
  ),
  1 => array (
    'volume' => 86,
    'edition' => 6,
  ),
  2 => array (
    'volume' => 86,
    'edition' => 1,
  ),
  3 => array (
    'volume' => 85,
    'edition' => 6,
  ),
  4 => array (
    'volume' => 67,
    'edition' => 7,
  ),
  5 => array (
    'volume' => 67,
    'edition' => 2,
  ),
)
?>

# プログラムの最後のarray_merge()は配列のインデックスを振りなおしているだけ


array_multisort()を使ったものと比較をしてみるとごちゃごちゃしてる。
それにforeach文を2回まわしているのも美しくない。


まあそれでも「一つの列をソートする」だけならこの方法でもいい。


でもこれだと「複数の列をソートする」ことができない。
つまりvolumeのソートとeditionのソートが同時にできないわけだ。
# いや、やるだけなら一応できるんだけど


その辺りもarray_multisort()を使うと簡単に実装できちゃう。


■2次元配列のソート:array_multisort()を利用したダブルソート
<?php
foreach ($data as $key => $row) {
  $volume[$key]  = $row['volume'];
  $edition[$key] = $row['edition'];
}// end foreach
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);
print_r($data);
?>


■実行結果
> array (
  0 => array (
    'volume' => 98,
    'edition' => 2,
  ),
  1 => array (
    'volume' => 86,
    'edition' => 1,
  ),
  2 => array (
    'volume' => 86,
    'edition' => 6,
  ),
  3 => array (
    'volume' => 85,
    'edition' => 6,
  ),
  4 => array (
    'volume' => 67,
    'edition' => 2,
  ),
  5 => array (
    'volume' => 67,
    'edition' => 7,
  ),
)


ソートの条件を増やすにはarray_multisort()に引数を増やすだけ。
SQLライクな感じでわかりやすい。

知らないってもったいないことだね





-- 2016/02/01 追加: 検索ワード
並べ替え、並び替え、並替え





Comments(5)

1  みやびさん  2013/06/21 (金) 13:25 ID:APDBg4O15
PHP5.5ならarray_columnが使えますが、超強烈ですよ
記事の例だと一度もforeach文使わずに書けますね
でもPHP5.5使える案件なんてないよ…

存在意義が分からない関数も多いですけど、
使える子も色々とあるので使い分けたいですね

2  シラサヤ  2013/06/21 (金) 16:18 ID:hi1aT2f15
array_column()みたよ。
foreach文で回さなくても指定のキーが取り出せるのな。

これが、
foreach ($data as $key => $row) {
$volume[$key] = $row['volume'];
}// end foreach

これで済むわけね。
$volume = array_column($data, 'volume');


なるほど便利だ

3  シラサヤ  2013/06/21 (金) 21:05 ID:hi1aT2f15
PHP 5.5.0がリリースされたのって6月20日じゃねえか。
アンテナたけえな

4  115ちゃん  2013/06/24 (月) 11:55 ID:pLRaYqE15
お~~~!!

5  みやびさん  2013/06/24 (月) 18:39 ID:c5Opgsa15
先々週くらいから
array_column()のページ出来てたっぽいですよ。

たまたまプログラミングしてる途中で
array_combine辺りの関数調べてる最中に「あれ?こんなのあったっけ?」ということで、
array_columnを見つけて、Version調べたらPHP5.5で萎えた覚えがあります