[PHP] array_multisortのソート後の注意点

2019年8月1日

PHP テクノロジー プログラミング

t f B! P L
PHPの配列ソートで、便利に使える"array_multisort"なのだが、ソート後の処理で発生した不具合を経験したので、その内容と対策を備忘録しておきます。 ちなみに、これまで手作業でソート作業していて、この関数を知ってから書いたブログは以下のURLです。 array_multisortとはなんぞや???という方は、事前に読んでみてください。 [PHP] 連想配列のソートで便利に使える”array_multisort” [PHP] 連想配列のソートで便利に使える"array_multisort"

サンプルコード

<?php $data = array( array( "id" => 1, "value" => "Sunday", "pv" => 1000 ), array( "id" => 2, "value" => "Monday", "pv" => 900 ), array( "id" => 3, "value" => "Tuesday", "pv" => 800 ), array( "id" => 4, "value" => "Wednesday", "pv" => 1500 ), array( "id" => 5, "value" => "Thersday", "pv" => 1200 ), array( "id" => 6, "value" => "Fryday", "pv" => 500 ), array( "id" => 7, "value" => "Saturday", "pv" => 700 ) ); $pvs = array(); foreach($data as $key => $val){ array_push($pvs,$val["pv"]); } array_multisort($pvs , SORT_ASC , SORT_NUMERIC , $data); print_r($data); $ php array_multisort.php Array ( [0] => Array ( [id] => 6 [value] => Fryday [pv] => 500 ) [1] => Array ( [id] => 7 [value] => Saturday [pv] => 700 ) [2] => Array ( [id] => 3 [value] => Tuesday [pv] => 800 ) [3] => Array ( [id] => 2 [value] => Monday [pv] => 900 ) [4] => Array ( [id] => 1 [value] => Sunday [pv] => 1000 ) [5] => Array ( [id] => 5 [value] => Thersday [pv] => 1200 ) [6] => Array ( [id] => 4 [value] => Wednesday [pv] => 1500 ) ) このサンプルプログラムで、問題なく多重連想配列を操作できるのですが、本来の配列変数を上書きされてしまうのと、わざわざソートしたい対象keyの値を抽出するのがめんどくさいですね。 そこで、もっといい方法がリファレンスページに掲載されていました。

リファレンスページに掲載されていたarray_msort関数が、かなり便利な件

PHPマニュアル「array_multisort」 https://www.php.net/manual/ja/function.array-multisort.php#91638 このページに書かれている以下の関数を実行すると、key値を指定するだけという、非常に簡単な操作でmultisortが実行できます。 function array_msort($array, $cols) { $colarr = array(); foreach ($cols as $col => $order) { $colarr[$col] = array(); foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); } } $eval = 'array_multisort('; foreach ($cols as $col => $order) { $eval .= '$colarr[\''.$col.'\'],'.$order.','; } $eval = substr($eval,0,-1).');'; eval($eval); $ret = array(); foreach ($colarr as $col => $arr) { foreach ($arr as $k => $v) { $k = substr($k,1); if (!isset($ret[$k])) $ret[$k] = $array[$k]; $ret[$k][$col] = $array[$k][$col]; } } return $ret; } これをPHPに搭載して、下記のように実行します。 $data2 = array_msort($data , array("pv"=>SORT_ASC)); print_r($data2); php array_multisort.php Array ( [5] => Array ( [id] => 6 [value] => Fryday [pv] => 500 ) [6] => Array ( [id] => 7 [value] => Saturday [pv] => 700 ) [2] => Array ( [id] => 3 [value] => Tuesday [pv] => 800 ) [1] => Array ( [id] => 2 [value] => Monday [pv] => 900 ) [0] => Array ( [id] => 1 [value] => Sunday [pv] => 1000 ) [4] => Array ( [id] => 5 [value] => Thersday [pv] => 1200 ) [3] => Array ( [id] => 4 [value] => Wednesday [pv] => 1500 ) ) とてもサックリと、実行結果を得ることができます。 非常にいい関数ですね。

トラブルポイントと解決方法

ネイティブ関数のarray_multisortと、追加のarray_msortの結果を比べてみると、違う点に気がつきませんか? 結果のトップレベル配列順番の数値が、array_msortの場合は変換前のモノを保持している点です。 これは、元配列にすぐに戻すことも可能だし、ソート変換した状態も保持してくれているので、非常に便利な状態ですが、このデータの取り出し方に注意しなければいけません。 トラブルの元になる得る原因は、この連想配列からデータを取り出す時に、for文で取り出すかforeachで取り出すかで、順番が変わってくるので、その点要注意です。

for

forで取り出すと、トップレベル配列順番の数値通りになるので、元の順番をキープした結果になり、

foreach

foreachの場合は、変換後(ソート実行後)の順番で取り出すことができるようになります。 ケースバーケースで、どちらかを使って行うのが良さそうです。 何も知らずにfor文だけを使って、ソートされていないと騒がないように気をつけましょう。 改めてarray_multisortはソートー便利 !!

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ