PHP配列をサブ配列値でソート


110

次の配列構造があります。

Array
        (
            [0] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

に基づいて、インクリメンタルな方法でアレイを注文する最良の方法は何ですか optionNumberですか?

したがって、結果は次のようになります。

Array
        (
            [0] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

回答:


204

を使用しusortます。

function cmp_by_optionNumber($a, $b) {
  return $a["optionNumber"] - $b["optionNumber"];
}

...

usort($array, "cmp_by_optionNumber");

PHP≥5.3では、代わりに無名関数を使用する必要があります。

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

上記のコードはどちらも$a['optionNumber']整数であると想定しています。@Stを使用します。ジョンソンが文字列の場合の解決策


PHP≥7.0では、オーバーフロー/切り捨ての問題を防ぐために、減算ではなく宇宙船演算子を<=>使用してください。

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

1
usortには使用する関数を提供する必要があるため、これは本当に役に立ちません。これは、頭を丸めることができない難しいビットです
Sjwdavies

17
さて、彼はちょうどあなたに使用する機能を与えました。そして、あなたはあなたが望むことをするための組み込み関数が常にあるわけではないことを受け入れる必要があります、あなたはそれを自分で書かなければなりません。比較関数では、2つの要素の並べ替え順序を示す1、0、または-1を返す必要があります。
Tesserex、2010年

1
私はusortをさらに調べましたが、実際にはかなりクールです。上記とは簡単な比較関数を書きましたが、「==」がありませんでした。助けてくれてありがとう
Sjwdavies

3
現在はクロージャとしても使用できます。--usort($ array、function($ a、$ b){return $ b ["optionNumber"]-$ a ["optionNumber"];});
Joeri、

1
@KiloumapL'artélon結果がの場合< 0、それはa前に現れるはずのソート関数に通知しbます。その場合は> 0b前に表示されaます。
kennytm 2018

57

使用する usort

 usort($array, 'sortByOption');
 function sortByOption($a, $b) {
   return strcmp($a['optionNumber'], $b['optionNumber']);
 }

7
@BenSinclair、それはケニーの解法が数値のためであるので、この解法は文字列のためです。どちらも正しいです:-)この代替案では+1。
kubilay 2013年

大文字小文字を区別しないソート利用strcasecmp代わりのstrcmpのために
user570605

配列の2番目の順序のキーを定義できますか?つまり、最初にoptionNumberでソートしてから、lastUpdatedでソートします。どうすればこのことができますか?
Bhavin Thummar、

16

私がすることによって両方のソリューションを使用KennyTMAJクイックをなど、多くの場合のために、この問題で助けることができる機能を思い付いたASCを使用するか、またはDESCを並べ替えたり、キーを保持し、あなたが持っている場合は、配列の子どもたちなどのオブジェクトを

これがこの関数です(宇宙船のオペレーターのため、PHP7以降で機能します)。

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if ($preserveKeys) {
        $c = [];
        if (is_object(reset($array))) {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v->$value);
            }
        } else {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v[$value]);
            }
        }
        $asc ? asort($b) : arsort($b);
        foreach ($b as $k => $v) {
            $c[$k] = $array[$k];
        }
        $array = $c;
    } else {
        if (is_object(reset($array))) {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
            });
        } else {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
            });
        }
    }

    return $array;
}

使用法:

sortBySubValue($array, 'optionNumber', true, false);

編集する

最初の部分はを使用uasort()して書き換えることができ、関数は短くなります(宇宙船の演算子のため、PHP7以降で機能します)。

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if (is_object(reset($array))) {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        });
    } else {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        });
    }
    return $array;
}

これは、ここで最も有用な答えです。一番上にあるはずです;)
Edi Budimilic

@EdiBudimilicありがとう、ありがとうございます!ちなみに私は私の答えを更新し、この関数の短いバージョンを追加しました:)
Pigalev Pavel

1
これを機能させるには、文字列を比較していたため、値と比較するとき>-(マイナス)ではなく(より大きい)を使用する必要がありました。それでも動作します。$a$b
James

1
@ジェームズあなたは正しい。私は答えを変更し、宇宙船オペレーター(<=>)の使用を追加しました。これで問題なく動作するはずです。
Pigalev Pavel

この大文字と小文字を区別しない方法はありますか?
loeffel

4

上記のような機能を使用すると、キーが削除されます。キーが重要な場合、次の関数はそれを維持します...しかし、foreachループはかなり非効率的です。

function subval_sort($a,$subkey) {
    foreach($a as $k=>$v) {
        $b[$k] = strtolower($v[$subkey]);
    }
    asort($b);
    foreach($b as $key=>$val) {
        $c[$key] = $a[$key];
    }
    return $c;
}
$array = subval_sort($array,'optionNumber');

高から低にしたい場合は、asortの代わりにarsortを使用します。

コードクレジット:http : //www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/


4

array_multisort()、array_map()の使用

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

print_r($array);

デモ


2
これは非常に簡単に機能します。ありがとうございました。私がしなければならなかったすべては私の列名を変更し、それはうまくいきました。
Kobus Myburgh

2
これにより、親配列のキーも保持されます
JonnyS

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