[PHP]ハッシュの入った配列を,ハッシュ値をキーにソートする

PHPで、例えば以下の様に沢山のハッシュテーブルが配列に格納されていたとします。
DBのテーブルとかをイメージすると分かりやすいかもしれません。

$dataList = array();
$dataList[] = array( "itemcode" => "10001", "itemname" => "みかん" );
$dataList[] = array( "itemcode" => "10010", "itemname" => "たまご" );
$dataList[] = array( "itemcode" => "10005", "itemname" => "りんご" );
$dataList[] = array( "itemcode" => "10002", "itemname" => "ぶどう" );
$dataList[] = array( "itemcode" => "10004", "itemname" => "とうふ" );



上記のデータをitemcode順に並び替えたい時、どの様にすれば良いでしょうか?
このような時、array_multisort()という関数を利用すると便利です。



まずは、array_multisort関数自体の使い方


という訳で、まずはarray_multisort関数の説明をマニュアルで確認してみます。

bool array_multisort( array &$arr [, mixed $arg = SORT_ASC 
                      [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
 
array_multisort() は、複数の配列を一度に、 
または、多次元の配列をその次元の一つでソートする際に使用可能です。 
この関数は、ソートの際にキーの相関を維持します。
 
連想配列のキー (string) は不変ですが、 数値添字は再度振り直されます。



…ドキュメントの文言だけでは意味が分からないので、例題を出して使い方のイメージを掴んでみます。



まずは、シンプルなサンプルです。

コード

$dataList = array( "e", "o", "h", "l", "l" );
$priority = array( 2, 5, 1, 3, 4 );
 
array_multisort( $priority, SORT_NUMERIC, $dataList );
var_dump( $dataList );
var_dump( $priority );



実行結果:

array
  0 => string 'h' (length=1)
  1 => string 'e' (length=1)
  2 => string 'l' (length=1)
  3 => string 'l' (length=1)
  4 => string 'o' (length=1)
 
array
  0 => int 1
  1 => int 2
  2 => int 3
  3 => int 4
  4 => int 5


第1引数で指定された配列の順(数値順/辞書順)に従って、第3引数の配列も並び替えてくれます。

第2引数はオプション指定で、第一引数のデータ型を指定します。
数値順にソートしたい場合はSORT_NUMERIC、文字コード順の場合はSORT_STRINGです。

一応、「array_multisort( $priority, $dataList );」といった感じで、データ型指定は省略可能なのですが、暗黙の型変換による、予期せぬ振る舞いを避けるために明示しておいたほうが無難です。



逆順にしたい場合は、SORT_DESCオプションを差し込みます。

$dataList = array( "e", "o", "h", "l", "l" );
$priority = array( 2, 5, 1, 3, 4 );
 
array_multisort( $priority, SORT_DESC, SORT_NUMERIC, $dataList );
var_dump( $dataList );
var_dump( $priority );



実行結果:

array
  0 => string 'o' (length=1)
  1 => string 'l' (length=1)
  2 => string 'l' (length=1)
  3 => string 'e' (length=1)
  4 => string 'h' (length=1)
 
array
  0 => int 5
  1 => int 4
  2 => int 3
  3 => int 2
  4 => int 1


SORT_DESC(降順) を省略した時は、SORT_ASC(昇順)がデフォルト値として指定されたと見なされます(明示することも可能です)。

array_multisort関数には他にも色々な使い方が有るのですが、”ハッシュの入った配列をソート”が目的ならここまで分かれば十分です。



“ハッシュの入った配列をソート”する


という訳で、本題に入ります。
ソートキーだけが入った配列があればよいので、以下の様なプログラムで並び替えが可能です。

コード

$dataList = array();
$dataList[] = array( "itemcode" => "10001", "itemname" => "みかん" );
$dataList[] = array( "itemcode" => "10010", "itemname" => "たまご" );
$dataList[] = array( "itemcode" => "10005", "itemname" => "りんご" );
$dataList[] = array( "itemcode" => "10002", "itemname" => "ぶどう" );
$dataList[] = array( "itemcode" => "10004", "itemname" => "とうふ" );
$priority = array();
foreach( $dataList as $data ) {
	$priority[] = $data[ "itemcode" ];
}
 
array_multisort( $priority, SORT_STRING, $dataList );
var_dump( $dataList );



実行結果

array
  0 => 
    array
      'itemcode' => string '10001' (length=5)
      'itemname' => string 'みかん' (length=9)
  1 => 
    array
      'itemcode' => string '10002' (length=5)
      'itemname' => string 'ぶどう' (length=9)
  2 => 
    array
      'itemcode' => string '10004' (length=5)
      'itemname' => string 'とうふ' (length=9)
  3 => 
    array
      'itemcode' => string '10005' (length=5)
      'itemname' => string 'りんご' (length=9)
  4 => 
    array
      'itemcode' => string '10010' (length=5)
      'itemname' => string 'たまご' (length=9)




複数のキーを元にソートする


ソートキーが2つある場合は、以下のようになります。

$dataList = array();
$dataList[] = array( "category" => "1", "itemcode" => "10001", "itemname" => "みかん" );
$dataList[] = array( "category" => "2", "itemcode" => "10010", "itemname" => "たまご" );
$dataList[] = array( "category" => "1", "itemcode" => "10005", "itemname" => "りんご" );
$dataList[] = array( "category" => "1", "itemcode" => "10002", "itemname" => "ぶどう" );
$dataList[] = array( "category" => "2", "itemcode" => "10004", "itemname" => "とうふ" );
 
$pri1 = array();
$pri2 = array();
foreach( $dataList as $data ) {
	$pri1[] = $data[ "category" ];
	$pri2[] = $data[ "itemcode" ];
}
 
array_multisort( $pri1, SORT_ASC,  SORT_STRING, 
                 $pri2, SORT_DESC, SORT_STRING, 
                 $dataList );
 
var_dump( $dataList );




実行結果

array
  0 => 
    array
      'category' => string '1' (length=1)
      'itemcode' => string '10005' (length=5)
      'itemname' => string 'りんご' (length=9)
  1 => 
    array
      'category' => string '1' (length=1)
      'itemcode' => string '10002' (length=5)
      'itemname' => string 'ぶどう' (length=9)
  2 => 
    array
      'category' => string '1' (length=1)
      'itemcode' => string '10001' (length=5)
      'itemname' => string 'みかん' (length=9)
  3 => 
    array
      'category' => string '2' (length=1)
      'itemcode' => string '10010' (length=5)
      'itemname' => string 'たまご' (length=9)
  4 => 
    array
      'category' => string '2' (length=1)
      'itemcode' => string '10004' (length=5)
      'itemname' => string 'とうふ' (length=9)



第1キーがカテゴリの昇順、第2キーが商品コードの降順にソートしています。
この例のように、各ソートキー毎に改行を入れてあげると可読性が高まります。


ソートキーが固定長である事が分かっており、ASC/DESCが混在しない場合は、以下のようにキー文字列を連結するのもありです。

foreach( $dataList as $data ) {
	$priority[] = $data[ "category" ] . "_" . $data[ "itemcode" ];
}
array_multisort( $priority, SORT_STRING, $dataList );




ハッシュポテト【McDonald’s FOOD STRAP 2】

関連記事

コメントを残す

メールアドレスが公開されることはありません。