多次元配列を値でソートする方法は?


1129

この配列を「order」キーの値でソートするにはどうすればよいですか?値は現在シーケンシャルですが、常にそうであるとは限りません。

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

    [2] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
)


最も簡単な方法は、ブラウザとノードの両方でネイティブに動作する同形ソート配列モジュールを使用して、あらゆるタイプの入力、計算フィールド、カスタムソート順をサポートすることです。
ロイド

回答:


1734

usortを試してください。まだPHP 5.2以前を使用している場合は、最初にソート関数を定義する必要があります。

function sortByOrder($a, $b) {
    return $a['order'] - $b['order'];
}

usort($myArray, 'sortByOrder');

PHP 5.3以降では、無名関数を使用できます。

usort($myArray, function($a, $b) {
    return $a['order'] - $b['order'];
});

そして最後にPHP 7では、宇宙船演算子を使用できます。

usort($myArray, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

これを多次元の並べ替えに拡張するには、最初の要素がゼロの場合、2番目/ 3番目の並べ替え要素を参照します。これをサブエレメントのソートに使用することもできます。

usort($myArray, function($a, $b) {
    $retval = $a['order'] <=> $b['order'];
    if ($retval == 0) {
        $retval = $a['suborder'] <=> $b['suborder'];
        if ($retval == 0) {
            $retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
        }
    }
    return $retval;
});

キーの関連付けを保持する必要がある場合は、次を使用しますuasort()- マニュアルの配列ソート関数の比較を参照してください


2
私の言い回しは少しずれています。編集します。私が意味したことは、PHP 5.3を使用していない場合、この特定のソートのためだけに特別な関数を作成する必要があるということです(これは何となくエレガントではありません)。それ以外の場合は、匿名関数をすぐに使用できます。
Christian Studer、

23
@ジョナサン:PHPが行うほとんどの作業を実際に見ることはできません。これは配列を取り、2つの要素で始まり、このユーザー定義関数に渡されます。次に、関数でそれらを比較します。最初の要素が2番目の要素より大きい場合は正の整数を返し、小さい場合は負の整数を返します。それらが等しい場合、0を返します。次に、PHPは他の2つの要素を関数に送信し、配列がソートされるまで送信を続けます。ここでの関数は非常に短く、整数を比較しない場合ははるかに複雑になる可能性があります。
Christian Studer、2012

61
Protip:uasort()配列のキーを保持したい場合に使用します。
thaddeusmt 2013

15
ソート可能な値が10進数である場合は注意してください。並べ替え関数が$ a = 1と$ b = 0.1の場合、差は0.9ですが、関数はint(この場合は0)を返すため、$ aと$ bは等しいと見なされ、正しく並べ替えられません。$ aが$ b以上であるかどうかを比較し、それに応じて-1、1、または0を返す方が信頼性が高くなります。
Greenlandi

37
見つけるのにしばらく時間がかかりました。逆順(DESC)をソートするには、$ aと$ bを切り替えます。つまり、$ b ['order']-$ a ['order']
JanWillem

285
function aasort (&$array, $key) {
    $sorter=array();
    $ret=array();
    reset($array);
    foreach ($array as $ii => $va) {
        $sorter[$ii]=$va[$key];
    }
    asort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii]=$array[$ii];
    }
    $array=$ret;
}

aasort($your_array,"order");

7
@ noc2spamお役に立ててうれしいですが、スタッダーの提案に従うことを検討してください
o0 '。

1
@Lohoris確かに私もチェックしています。私がこの質問を見つけられなかったとしたら、昨日はオフィスで厳しい日だったでしょう:-)
Gogol

うーん、答えを追加することはできません。まあ、ここに置いておきます。これらの愚かなポイントは必要ありません。多次元ソートの場合、(ほとんど)同じものです(申し訳ありませんが、コピーして貼り付け、再フォーマットする必要があります):function aasort(&$ array 、$ key1、$ key2、$ key3){$ sorter = array(); $ ret = array(); リセット($配列); foreach($ array as $ ii => $ va){$ sorter [$ ii] = getPrice($ va [$ key1] [$ key2] [$ key3]); } arsort($ sorter); foreach($ sorter as $ ii => $ va){$ ret [$ ii] = $ array [$ ii]; } $ array = $ ret; }
Jaxx0rr 2014年

3
上記の回答よりもはるかに簡単に適用できます
Marcel


270

私はこの関数を使用します:

function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
    $sort_col = array();
    foreach ($arr as $key=> $row) {
        $sort_col[$key] = $row[$col];
    }

    array_multisort($sort_col, $dir, $arr);
}


array_sort_by_column($array, 'order');

3
とてもうまくいきます。並べ替え方向を追加できる独自のソリューション。ありがとう!
Ivo Pereira

2
並べ替えの方向と多くの追加機能をサポートする別の方法については、ここ私の答えを確認することをお勧めします。また、使用array_multisortしないため、事前に割り当てる必要がないという利点があり$sort_col、時間とメモリを節約できます。 。
2013年

私にとってはうまく機能しますが、... &$arrだけでなく、なぜ指定する必要があるのですか$arr
Radu Murzea 2013

2
@RaduMurzeaにより、配列は参照によって渡され、関数がコピーを受け取るのではなく、関数によって変更できます
Tom Haigh

1
@AdrianP。:配列は参照によって渡されるため、ソートされたコピーを返すのではなく、渡された配列を変更します
Tom Haigh

72

私は通常usortを使用し、独自の比較関数を渡します。この場合、それは非常に簡単です:

function compareOrder($a, $b)
{
  return $a['order'] - $b['order'];
}
usort($array, 'compareOrder');

宇宙船オペレーターを使用するPHP 7では:

usort($array, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

4
くそー、私は30秒遅くなりました。$ a-$ bではありませんか?
Christian Studer

3
私はいつもこれを間違えます。マニュアルから考えてみましょう。最初の引数が2番目の引数よりも小さいと見なされる場合、戻り値はゼロ未満でなければなりません。したがって、$a['order']3で$b['order']6の場合、-3を返します。正しい?
Jan Fabry

3
さて、あなたはb-aを返すので、それは3になります。したがって、正しくソートされません。
Christian Studer、2010

26
ああ。OK。私はあなたの頭の中のアイデアがあなたが生み出す言葉と一致しない非論理演算を使っていました。これは、金曜日の午後に最も頻繁に調査されます。
Jan Fabry

答えは上記のいくつかのケースでは、戻り、間違った結果..です参照stackoverflow.com/questions/50636981/...
ビラルアーメド

45

これを達成する1つのアプローチは次のようになります

    $new = [
              [
                'hashtag' => 'a7e87329b5eab8578f4f1098a152d6f4',
                'title' => 'Flower',
                'order' => 3,
              ],

              [
                'hashtag' => 'b24ce0cd392a5b0b8dedc66c25213594',
                'title' => 'Free',
                'order' => 2,
              ],

              [
                'hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
                'title' => 'Ready',
                'order' => 1,
              ],
    ];

    $keys = array_column($new, 'order');

    array_multisort($keys, SORT_ASC, $new);

    var_dump($new);

結果:

    Array
    (
        [0] => Array
            (
                [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
                [title] => Ready
                [order] => 1
            )

        [1] => Array
            (
                [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
                [title] => Free
                [order] => 2
            )

        [2] => Array
            (
                [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
                [title] => Flower
                [order] => 3
            )

    )

18

「タイトル」キーの値で配列をソートするには、次のようにします。

uasort($myArray, function($a, $b) {
    return strcmp($a['title'], $b['title']);
});

strcmpは文字列を比較します。

uasort()は、定義されたとおりに配列キーを維持します。


strcmpはvarchar型の注目すべきヘルプです。私はこの答えが短くて速いのが好きでした
StudioX

17
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

これは大文字と小文字の両方のアルファベットを処理します。


4
これは、特定の配列キーによるソートの問題にどのように答えますか?
Seano

12

使用array_multisort()array_map()

array_multisort(array_map(function($element) {
      return $element['order'];
  }, $array), SORT_ASC, $array);

print_r($array);

デモ


このアプローチは通知を出すことに注意してください。array_multisort最初のパラメータを参照します。
Kami Yang

5

最も柔軟なアプローチは、この方法を使用することです

Arr::sortByKeys(array $array, $keys, bool $assoc = true): array

ここに理由があります:

  • 任意のキーで並べ替えることができます('key1.key2.key3'またはのようにネストされている['k1', 'k2', 'k3']

  • 連想配列と非連想配列の両方で機能します($assocフラグ)

  • 参照を使用しません-新しいソートされた配列を返します

あなたの場合、それは次のように簡単です:

$sortedArray = Arr::sortByKeys($array, 'order');

このメソッドは、このライブラリの一部です。


1

それに直面しよう:phpには、すべての配列ソートシナリオを適切に処理するための単純な箱から出し関数はありません。

このルーチンは直感的です。つまり、デバッグとメンテナンスが高速になります。

// automatic population of array
$tempArray = array();
$annotations = array();
// ... some code
// SQL $sql retrieves result array $result 
// $row[0] is the ID, but is populated out of order (comes from 
// multiple selects populating various dimensions for the same DATE 
// for example
while($row = mysql_fetch_array($result)) {
    $needle = $row[0];
    arrayIndexes($needle);  // create a parallel array with IDs only
    $annotations[$needle]['someDimension'] = $row[1]; // whatever
}
asort($tempArray);
foreach ($tempArray as $arrayKey) {
    $dataInOrder = $annotations[$arrayKey]['someDimension']; 
    // .... more code
}

function arrayIndexes ($needle) {
    global $tempArray;
    if (!in_array($needle,$tempArray)) {
        array_push($tempArray,$needle);
    }
}

4
「それに直面しよう:phpには、すべての配列ソートシナリオを適切に処理するための単純な箱から出してすぐの関数はありません。」これがまさにusort / ksort / asortが^^ 'のために設計したものです
Ben Cassinat

3
実際、PHPに すべての配列ソートシナリオを処理するために使用できる多くのソート関数があります。
アシアック

デバッグとメンテナンスに関して、の使用globalは非常に危険であり、一般的には推奨されませんmysql_fetch_arrayOPのソース配列の代わりにこの質問に対してなぜデモンストレーションが行われているのか、そしてコードが何をしているのか、結果がどのようになるのかを説明できないのですか?全体として、これは望ましい最終結果を達成する上で非常に複雑なアプローチです。
fyrye

@tonygil私はあなたの答えとOPのデータセットからあなたの期待される結果が何であるかを決定することができません。自明かもしれませんが、あなたの答えがOPの質問にどのように答えるかはわかりません。ただし、see:3v4l.org/FEeFCを使用する代わりに参照渡しすることができglobalます。これにより、変更してグローバルにアクセスできる変数ではなく、明示的に定義された変数が生成されます。
fyrye

0

次のように、複数の値の多次元配列をソートすることもできます

$arr = [
    [
        "name"=> "Sally",
        "nick_name"=> "sal",
        "availability"=> "0",
        "is_fav"=> "0"
    ],
    [
        "name"=> "David",
        "nick_name"=> "dav07",
        "availability"=> "0",
        "is_fav"=> "1"
    ],
    [
        "name"=> "Zen",
        "nick_name"=> "zen",
        "availability"=> "1",
        "is_fav"=> "0"
    ],
    [
        "name"=> "Jackson",
        "nick_name"=> "jack",
        "availability"=> "1",
        "is_fav"=> "1"
    ],
    [
        "name"=> "Rohit",
        "nick_name"=> "rod",
        "availability"=> "0",
        "is_fav"=> "0"
    ],

];

usort($arr,function($a,$b){
    $c = $b['is_fav'] - $a['is_fav'];
    $c .= $b['availability'] - $a['availability'];
    $c .= strcmp($a['nick_name'],$b['nick_name']);
    return $c;
});

を使用して出力print_r($arr)

Array
(
    [0] => Array
        (
            [name] => Jackson
            [nick_name] => jack
            [availability] => 1
            [is_fav] => 1
        )

    [1] => Array
        (
            [name] => David
            [nick_name] => dav07
            [availability] => 0
            [is_fav] => 1
        )

    [2] => Array
        (
            [name] => Zen
            [nick_name] => zen
            [availability] => 1
            [is_fav] => 0
        )

    [3] => Array
        (
            [name] => Rohit
            [nick_name] => rod
            [availability] => 0
            [is_fav] => 0
        )

    [4] => Array
        (
            [name] => Sally
            [nick_name] => sal
            [availability] => 0
            [is_fav] => 0
        )

)

PS)strcmpを使用すると、文字列を比較するのに適したオプションになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.