PHPプログラミング

レシピ

配列

多次元配列のソート:array_multisort関数

array_multisort関数を使って、多次元配列を特定のキーを軸にして並び替える方法について解説します。

この記事のポイント

  • 多次元配列を特定の値を軸にしてソートする
  • ソートの軸になる値を2つ以上指定する

目次

ものすごく便利な多次元配列のソート

単一の配列のソートは簡単ですが、2次元以上の多次元になっている配列をソートしたいときはソートの基準となるキーや値が複数になるため複雑になります。

例えば、次のような2次元配列のデータがあるとします。

多次元配列の例

$array = array(
    array(
        'id' =>1,
        'name' =>'柴犬',
        'age' =>8,
        'regist_datetime' =>'2017-02-01 10:00'
    ),
    array(
        'id' =>2,
        'name' =>'ポメラニアン',
        'age' =>3,
        'regist_datetime' =>'2017-02-15 10:00'
    ),
    array(
        'id' =>5,
        'name' =>'ゴールデンレトリバー',
        'age' =>8,
        'regist_datetime' =>'2017-02-16 15:00'
    ),
    array(
        'id' =>6,
        'name' =>'グレイハウンド',
        'age' =>6,
        'regist_datetime' =>'2017-02-16 16:30'
    ),
    array(
        'id' =>8,
        'name' =>'シベリアンハスキー',
        'age' =>3,
        'regist_datetime' =>'2017-02-16 19:00'
    )
);

この配列に対して、年齢を表す「age」の値を基準に昇順に並べ、さらに値が同じ場合は「id」を降順に並べたいとします。
このように多次元配列で複数の値を軸にしてソートしたい場合、単一の配列よりもやや複雑ですがarray_multisort関数を使うことで意図したソートを実現できます。

コード例

<?php

// 配列の初期化
$array = array();
$id_array = array();
$age_array = array();

// 多次元配列を作成
$array = array(
    array(
        'id' => 1,
        'name' => '柴犬',
        'age' => 8,
        'regist_datetime' => '2017-02-01 10:00'
    ),
    array(
        'id' => 2,
        'name' => 'ポメラニアン',
        'age' => 3,
        'regist_datetime' => '2017-02-15 10:00'
    ),
    array(
        'id' => 5,
        'name' => 'ゴールデンレトリバー',
        'age' => 8,
        'regist_datetime' => '2017-02-16 15:00'
    ),
    array(
        'id' => 6,
        'name' => 'グレイハウンド',
        'age' => 6,
        'regist_datetime' => '2017-02-16 16:30'
    ),
    array(
        'id' => 8,
        'name' => 'シベリアンハスキー',
        'age' => 3,
        'regist_datetime' => '2017-02-16 19:00'
    )
);

// ソートの基準となる「id」と「age」を配列に入れる
foreach( $array as $value) {
    $id_array[] = $value['id'];
    $age_array[] = $value['age'];
}

// ソート前の配列を出力
var_dump($array);

// ソート実行
array_multisort( $age_array, SORT_ASC, SORT_NUMERIC, $id_array, SORT_DESC, SORT_NUMERIC, $array);

// ソート後の配列を出力
var_dump($array);

配列のソート実行前、実行後はそれぞれ次のようになります。

ソート前の出力例

array(5) {
    [0]=> array(4) {
        ["id"]=> int(1)
        ["name"]=> string(6) "柴犬"
        ["age"]=> int(8)
        ["regist_datetime"]=> string(16) "2017-02-01 10:00"
    }
    [1]=> array(4) {
        ["id"]=> int(2)
        ["name"]=> string(18) "ポメラニアン"
        ["age"]=> int(3)
        ["regist_datetime"]=> string(16) "2017-02-15 10:00"
    }
    [2]=> array(4) {
        ["id"]=> int(5)
        ["name"]=> string(30) "ゴールデンレトリバー"
        ["age"]=> int(8)
        ["regist_datetime"]=> string(16) "2017-02-16 15:00"
    }
    [3]=> array(4) {
        ["id"]=> int(6)
        ["name"]=> string(21) "グレイハウンド"
        ["age"]=> int(6)
        ["regist_datetime"]=> string(16) "2017-02-16 16:30"
    }
    [4]=> array(4) {
        ["id"]=> int(8)
        ["name"]=> string(27) "シベリアンハスキー"
        ["age"]=> int(3)
        ["regist_datetime"]=> string(16) "2017-02-16 19:00"
    }
}

ソート後の出力例

array(5) {
    [0]=> array(4) {
        ["id"]=> int(8)
        ["name"]=> string(27) "シベリアンハスキー"
        ["age"]=> int(3)
        ["regist_datetime"]=> string(16) "2017-02-16 19:00"
    }
    [1]=> array(4) {
        ["id"]=> int(2)
        ["name"]=> string(18) "ポメラニアン"
        ["age"]=> int(3)
        ["regist_datetime"]=> string(16) "2017-02-15 10:00"
    }
    [2]=> array(4) {
        ["id"]=> int(6)
        ["name"]=> string(21) "グレイハウンド"
        ["age"]=> int(6)
        ["regist_datetime"]=> string(16) "2017-02-16 16:30"
    }
    [3]=> array(4) {
        ["id"]=> int(5)
        ["name"]=> string(30) "ゴールデンレトリバー"
        ["age"]=> int(8)
        ["regist_datetime"]=> string(16) "2017-02-16 15:00"
    }
    [4]=> array(4) {
        ["id"]=> int(1)
        ["name"]=> string(6) "柴犬"
        ["age"]=> int(8)
        ["regist_datetime"]=> string(16) "2017-02-01 10:00"
    }
}

意図した通り、年齢の昇順、idの降順で配列がソートされました。
array_multisort関数は、次のようにパラメータを受け取ってソートを行います。

array_multisort関数の使い方

array_multisort( ソートの軸となる配列(1), 並び順(1), ソートするデータの型(1), ソートの軸となる配列(2), 並び順(2), ソートするデータの型(2), ソートしたい配列);

上記のように、ソートの基準データの指定はデータの入った配列、並び順の指定、データの型の3つを1セットに指定します。
この中で、「並び順」と「データの型」はオプションとなるため省略できます。

この関数は実行すると、ソートした後の配列が自動的に「ソートしたい配列」で指定した配列に格納されます。
返り値はソートに成功したら「true」、失敗した場合は「false」です。

今回のコード例ではソートの軸になるデータを「年齢」と「id」の2つ設定していますが、1つでも3つでも、もしくはそれ以上を指定することも可能です。

ソートの軸となる配列が1つの場合

array_multisort( ソートの軸となる配列, 並び順, ソートするデータの型, ソートしたい配列);

ソートの軸となる配列が3つの場合

array_multisort( ソートの軸となる配列(1), 並び順(1), ソートするデータの型(1), ソートの軸となる配列(2), 並び順(2), ソートするデータの型(2), ソートの軸となる配列(3), 並び順(3), ソートするデータの型(3), ソートしたい配列);

今回の配列でソートする軸の配列を3つにした場合は、次のようになります。

ソートの軸とが3つのコード例

array_multisort( $age_array, SORT_ASC, SORT_NUMERIC, $id_array, SORT_DESC, SORT_NUMERIC, $name_array, SORT_ASC, SORT_STRING, $array);

ソートの軸となる配列はソート実行前に用意します。
この配列はソートする値のみが入っている状態にする必要があります。

上記コードではforeach文で$arrayのデータを1つずつ取り出して、$age_array$id_arrayにそれぞれの値を格納して作成しています。

// ソートの基準となる「id」と「age」を配列に入れる
foreach( $array as $value) {
    $id_array[] = $value['id'];
    $age_array[] = $value['age'];
}

あとはこの配列をarray_multisort関数に渡して実行するだけでOKです。

データの型について

つい忘れがちですが、軸となるデータの型はしっかり指定しておいた方が確実にソートすることができます。
指定できる型は次の6種類です。

定数説明
SORT_REGULAR型の変換をせずに比較
SORT_NUMERIC数値として比較
SORT_STRING文字列として比較
SORT_LOCALE_STRING使用している言語を踏まえたうえで、文字列として比較。言語はsetlocale関数で指定します。
SORT_NATURAL「自然順」で、文字列として比較
SORT_FLAG_CASEアルファベットの大文字、小文字を区別しないでソートの比較。SORT_STRINGなどと論理和で指定して実行

最後の「SORT_FLAG_CASE」だけやや分かりづらいですが、論理和を使った指定は次のように「| (パイプライン)」を使って行います。

コード例

array_multisort( $name_array, SORT_DESC, SORT_STRING | SORT_FLAG_CASE, $array);

こちらの記事は役に立ちましたか?

ありがとうございます。
もしよろしければ、あわせてフィードバックや要望などをご入力ください。

コメントありがとうございます!
運営の参考にさせていただきます。