PHPで配列とデータを並べ替えるにはどうすればよいですか?

298
deceze 2013-06-29 01:53.

この質問は、PHPでの配列の並べ替えに関する質問のリファレンスとして意図されています。あなたの特定のケースがユニークで新しい質問に値すると考えるのは簡単ですが、ほとんどは実際にはこのページの解決策の1つのマイナーなバリエーションです。

質問がこれと重複して閉じられた場合は、以下のすべてと著しく異なる理由を説明できる場合にのみ、質問を再開するように依頼してください。

PHPで配列を並べ替えるにはどうすればよいですか?PHPで複雑な配列
を並べ替えるにはどうすればよいですか? PHPでオブジェクトの配列を並べ替えるにはどうすればよいですか?


  1. 基本的な1次元配列。含む 多次元配列、含む。オブジェクトの配列; 含む ある配列を別の配列に基づいてソートする

  2. SPLによるソート

  3. 安定ソート

PHPの既存の関数を使用した実際的な回答については、1を参照してください。ソートアルゴリズム(PHPの関数が実装し、非常に複雑なケースで必要になる可能性がある)に関する学術的な詳細な回答については、2を参照してください。

10 answers

170
deceze 2013-06-29 01:53.

基本的な1次元配列

$array = array(3, 5, 2, 8);

該当するソート機能:

  • sort
  • rsort
  • asort
  • arsort
  • natsort
  • natcasesort
  • ksort
  • krsort

これらの違いは、キーと値の関連付けが保持されるかどうか( " a"関数)、ローからハイまたはリバースrにソートするか( " ")、値またはキーをソートするか( " k")、および値を比較する方法だけです。 ( " nat"対通常)。参照http://php.net/manual/en/array.sorting.phpを概観し、詳細へのリンクについて。

オブジェクトの配列を含む多次元配列

$array = array(
    array('foo' => 'bar', 'baz' => 42),
    array('foo' => ...,   'baz' => ...),
    ...
);

$array各エントリのキー「foo」でソートする場合は、カスタム比較関数が必要です。上記sortおよび関連する関数は、比較およびソートの方法を知っている単純な値で機能します。PHPは、単純に何をすべきかを「知らない」複雑な値のようなarray('foo' => 'bar', 'baz' => 42)ものの、だからあなたはそれを言う必要があります。

そのためには、比較関数を作成する必要があります。その関数は2つの要素を取り0、これらの要素が等しいと見なされる0場合、最初の値が低い場合よりも低い値、および0最初の値が高い場合よりも高い値を返す必要があります。必要なのはそれだけです。

function cmp(array $a, array $b) {
    if ($a['foo'] < $b['foo']) {
        return -1;
    } else if ($a['foo'] > $b['foo']) {
        return 1;
    } else {
        return 0;
    }
}

多くの場合、コールバックとして無名関数を使用する必要があります。メソッドまたは静的メソッドを使用する場合は、PHPでコールバックを指定する他の方法を参照してください。

次に、次のいずれかの関数を使用します。

繰り返しになりますが、キーと値の関連付けを維持し、値またはキーで並べ替えるかどうかだけが異なります。詳細については、ドキュメントをお読みください。

使用例:

usort($array, 'cmp');

usort配列から2つの項目を取得cmpし、それらを使用して関数を呼び出します。したがってcmp()$aasarray('foo' => 'bar', 'baz' => 42)およびasanotherで呼び出さ$barray('foo' => ..., 'baz' => ...)ます。次に、関数は、usortどちらの値が大きいか、またはそれらが等しいかどうかを返します。配列がソートされるまで、とにusort異なる値を渡してこのプロセスを繰り返します。この関数は、何度も呼び出されます少なくとも内の値があるとして何回も異なるの値の組み合わせで、そして毎回。$a$bcmp$array$a$b

このアイデアに慣れるには、これを試してください。

function cmp($a, $b) {
    echo 'cmp called with $a:', PHP_EOL;
    var_dump($a);
    echo 'and $b:', PHP_EOL;
    var_dump($b);
}

2つのアイテムを比較するカスタムの方法を定義するだけで、必要なのはそれだけです。これは、あらゆる種類の値で機能します。

ちなみに、これはどの値でも機能します。値は複雑な配列である必要はありません。実行したいカスタム比較がある場合は、単純な数値配列でも実行できます。

sort 参照でソートし、有用なものは何も返しません!

配列はその場でソートされることに注意してください。戻り値を何かに割り当てる必要はありません。$array = sort($array)配列はtrue、ソートされた配列ではなく、に置き換えられます。sort($array);うまくいきます。

カスタム数値比較

baz数値のキーで並べ替える場合は、次の操作を行うだけです。

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

PoWEr oF MATHのおかげで、これは、$aより小さいか、等しいか、より大きいかに応じて、<0、0、または> 0の値を返します$b

float値がに減少し、int精度が失われるため、これは値に対してはうまく機能しないことに注意してください。明示的なを使用し-1、代わりに値01返します。

オブジェクト

オブジェクトの配列がある場合、それは同じように機能します。

function cmp($a, $b) {
    return $a->baz - $b->baz;
}

関数

関数の呼び出しなど、比較関数内で必要なことは何でもできます。

function cmp(array $a, array $b) {
    return someFunction($a['baz']) - someFunction($b['baz']);
}

文字列

最初の文字列比較バージョンのショートカット:

function cmp(array $a, array $b) {
    return strcmp($a['foo'], $b['foo']);
}

strcmp期待だまさにんcmpここで、それを返す-10または1

宇宙船オペレーター

PHP 7では、宇宙船演算子が導入されました。これは、タイプ間の比較よりも等しい/小さい/大きいを統合および簡素化します。

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

複数のフィールドで並べ替え

主にfoo、で並べ替えたいがfoo、2つの要素が等しい場合は、baz次のように並べ替えます。

function cmp(array $a, array $b) {
    if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
        return $cmp;
    } else {
        return $a['baz'] - $b['baz'];
    }
}

おなじみの人にとって、これはORDER BY foo, baz。を使用したSQLクエリと同等です。
また、この非常に簡潔なバージョン、任意の数のキーに対してこのような比較関数を動的に作成する方法も参照してください。

手動の静的な順序に並べ替える

要素を「foo」、「bar」、「baz」などの手動順序」に並べ替える場合:

function cmp(array $a, array $b) {
    static $order = array('foo', 'bar', 'baz');
    return array_search($a['foo'], $order) - array_search($b['foo'], $order);
}

上記のすべてについて、PHP 5.3以降を使用している場合(そして実際に使用する必要がある場合)、コードを短くするために無名関数を使用し、別のグローバル関数が浮かんでいるのを防ぎます。

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

これが、複雑な多次元配列の並べ替えがいかに簡単であるかを示しています。繰り返しになりますが、PHPに、2つの項目のどちらが「大きい」かを判断する方法を教えるという観点から考えてみてください。PHPに実際のソートを任せます。

また、上記のすべてについて、昇順と降順を切り替えるには$a$b引数と引数を入れ替えるだけです。例えば:

return $a['baz'] - $b['baz']; // ascending
return $b['baz'] - $a['baz']; // descending

ある配列を別の配列に基づいてソートする

そして、独特のものarray_multisortがあります。これを使用すると、ある配列を別の配列に基づいて並べ替えることができます。

$array1 = array( 4,   6,   1);
$array2 = array('a', 'b', 'c');

ここで期待される結果は次のとおりです。

$array2 = array('c', 'a', 'b');  // the sorted order of $array1

array_multisortそこに到達するために使用します:

array_multisort($array1, $array2);

PHP 5.5.0以降でarray_columnは、多次元配列から列を抽出し、その列で配列を並べ替えることができます。

array_multisort(array_column($array, 'foo'), SORT_DESC, $array);

どちらの方向にも、それぞれ複数の列で並べ替えることができます。

array_multisort(array_column($array, 'foo'), SORT_DESC,
                array_column($array, 'bar'), SORT_ASC,
                $array);

PHP 7.0.0以降、オブジェクトの配列からプロパティを抽出することもできます。


より一般的なケースがある場合は、この回答を自由に編集してください。

139
Baba 2013-06-29 02:11.

さて、ほとんどの基本的な方法はすでにdecezeでカバーされています私は他の種類のソートを調べようとします

SPLによるソート

SplHeap

class SimpleHeapSort extends SplHeap {
    public function compare($a, $b) {
        return strcmp($a, $b);
    }
}

// Let's populate our heap here (data of 2009)
$heap = new SimpleHeapSort();
$heap->insert("a");
$heap->insert("b");
$heap->insert("c");

echo implode(PHP_EOL, iterator_to_array($heap));

出力

c
b
a

SplMaxHeap

SplMaxHeapクラスは、ヒープの主な機能を提供し、最大値を最上位に保ちます。

$heap = new SplMaxHeap();
$heap->insert(1);
$heap->insert(2);
$heap->insert(3);

SplMinHeap

SplMinHeapクラスは、ヒープの主な機能を提供し、最小値を最上位に保ちます。

$heap = new SplMinHeap ();
$heap->insert(3);
$heap->insert(1);
$heap->insert(2);

他の種類の並べ替え

バブルソート

バブルソートに関するウィキペディアの記事から

バブルソートは、誤ってシンクソートと呼ばれることもある単純なソートアルゴリズムであり、ソートするリストを繰り返しステップ実行し、隣接するアイテムの各ペアを比較し、順序が間違っている場合はそれらを交換します。リストのパススルーは、スワップが不要になるまで繰り返されます。これは、リストがソートされていることを示します。アルゴリズムの名前は、小さい要素がリストの一番上に「バブル」する方法から付けられます。要素を操作するために比較のみを使用するため、比較ソートです。アルゴリズムは単純ですが、他のほとんどのソートアルゴリズムは、大きなリストに対してより効率的です。

function bubbleSort(array $array) {
    $array_size = count($array);
    for($i = 0; $i < $array_size; $i ++) {
        for($j = 0; $j < $array_size; $j ++) {
            if ($array[$i] < $array[$j]) {
                $tem = $array[$i];
                $array[$i] = $array[$j];
                $array[$j] = $tem;
            }
        }
    }
    return $array;
}

選択ソート

選択ソートに関するウィキペディアの記事から

コンピュータサイエンスでは、選択ソートはソートアルゴリズム、具体的にはインプレース比較ソートです。O(n2)の時間計算量があり、大きなリストでは非効率的であり、一般に、同様の挿入ソートよりもパフォーマンスが低下します。選択ソートはその単純さで注目されており、特定の状況、特に補助メモリが制限されている場合、より複雑なアルゴリズムよりもパフォーマンス上の利点があります。

function selectionSort(array $array) {
    $length = count($array);
    for($i = 0; $i < $length; $i ++) {
        $min = $i;
        for($j = $i + 1; $j < $length; $j ++) {
            if ($array[$j] < $array[$min]) {
                $min = $j;
            }
        }
        $tmp = $array[$min];
        $array[$min] = $array[$i];
        $array[$i] = $tmp;
    }
    return $array;
}

挿入ソート

挿入ソートに関するウィキペディアの記事から

挿入ソートは、最終的にソートされた配列(またはリスト)を一度に1つのアイテムで作成する単純なソートアルゴリズムです。大規模なリストでは、クイックソート、ヒープソート、マージソートなどのより高度なアルゴリズムよりも効率がはるかに低くなります。ただし、挿入ソートにはいくつかの利点があります。

function insertionSort(array $array) {
    $count = count($array);
    for($i = 1; $i < $count; $i ++) {

        $j = $i - 1;
        // second element of the array
        $element = $array[$i];
        while ( $j >= 0 && $array[$j] > $element ) {
            $array[$j + 1] = $array[$j];
            $array[$j] = $element;
            $j = $j - 1;
        }
    }
    return $array;
}

シェルソート

シェルソートに関するウィキペディアの記事から

シェルソートは、シェルソートまたはシェルメソッドとも呼ばれ、インプレース比較ソートです。挿入やバブルソートなどの交換ソートを一般化するために、隣接する要素で終了する前に、離れた要素との要素の比較と交換を開始します。

function shellSort(array $array) {
    $gaps = array(
            1,
            2,
            3,
            4,
            6
    );
    $gap = array_pop($gaps);
    $length = count($array);
    while ( $gap > 0 ) {
        for($i = $gap; $i < $length; $i ++) {
            $tmp = $array[$i];
            $j = $i;
            while ( $j >= $gap && $array[$j - $gap] > $tmp ) {
                $array[$j] = $array[$j - $gap];
                $j -= $gap;
            }
            $array[$j] = $tmp;
        }
        $gap = array_pop($gaps);
    }
    return $array;
}

コムソート

コムソートに関するウィキペディアの記事から

コムソートは、1980年にWlodzimierz Dobosiewiczによって最初に設計された比較的単純なソートアルゴリズムです。その後、1991年にStephenLaceyとRichardBoxによって再発見されました。コムソートはバブルソートを改善します。

function combSort(array $array) {
    $gap = count($array);
    $swap = true;
    while ( $gap > 1 || $swap ) {
        if ($gap > 1)
            $gap /= 1.25;
        $swap = false;
        $i = 0;
        while ( $i + $gap < count($array) ) {
            if ($array[$i] > $array[$i + $gap]) {
                // swapping the elements.
                list($array[$i], $array[$i + $gap]) = array(
                        $array[$i + $gap],
                        $array[$i]
                );
                $swap = true;
            }
            $i ++;
        }
    }
    return $array;
}

マージソート

マージソートに関するウィキペディアの記事から

コンピュータサイエンスでは、マージソート(一般的にスペルト小麦のマージソート)は、O(n log n)比較ベースのソートアルゴリズムです。ほとんどの実装は安定したソートを生成します。つまり、実装はソートされた出力で等しい要素の入力順序を保持します。

function mergeSort(array $array) {
    if (count($array) <= 1)
        return $array;

    $left = mergeSort(array_splice($array, floor(count($array) / 2)));
    $right = mergeSort($array);

    $result = array();

    while ( count($left) > 0 && count($right) > 0 ) {
        if ($left[0] <= $right[0]) {
            array_push($result, array_shift($left));
        } else {
            array_push($result, array_shift($right));
        }
    }
    while ( count($left) > 0 )
        array_push($result, array_shift($left));

    while ( count($right) > 0 )
        array_push($result, array_shift($right));

    return $result;
}

クイックソート

クイックソートに関するウィキペディアの記事から

クイックソート、またはパーティション交換ソートは、Tony Hoareによって開発されたソートアルゴリズムであり、平均してO(n log n)の比較を行ってn個のアイテムをソートします。最悪の場合、この動作はまれですが、O(n2)の比較を行います。

function quickSort(array $array) {
    if (count($array) == 0) {
        return $array;
    }
    $pivot = $array[0];
    $left = $right = array();
    for($i = 1; $i < count($array); $i ++) {
        if ($array[$i] < $pivot) {
            $left[] = $array[$i];
        } else {
            $right[] = $array[$i];
        }
    }
    return array_merge(quickSort($left), array(
            $pivot
    ), quickSort($right));
}

順列ソート

順列ソートに関するウィキペディアの記事から

順列ソート。ソートされたものが見つかるまで、入力配列/リストの可能な順列を生成することによって進行します。

function permutationSort($items, $perms = array()) {
    if (empty($items)) {
        if (inOrder($perms)) {
            return $perms;
        }
    } else {
        for($i = count($items) - 1; $i >= 0; -- $i) {
            $newitems = $items;
            $newperms = $perms;
            list($foo) = array_splice($newitems, $i, 1);
            array_unshift($newperms, $foo);
            $res = permutationSort($newitems, $newperms);
            if ($res) {
                return $res;
            }
        }
    }
}

function inOrder($array) {
    for($i = 0; $i < count($array); $i ++) {
        if (isset($array[$i + 1])) {
            if ($array[$i] > $array[$i + 1]) {
                return False;
            }
        }
    }
    return True;
}

基数ソート

基数ソートに関するウィキペディアの記事から

コンピュータサイエンスでは、基数ソートは非比較の整数ソートアルゴリズムであり、同じ重要な位置と値を共有する個々の桁でキーをグループ化することにより、整数キーでデータをソートします。

// Radix Sort for 0 to 256
function radixSort($array) {
    $n = count($array);
    $partition = array();

    for($slot = 0; $slot < 256; ++ $slot) {
        $partition[] = array();
    }

    for($i = 0; $i < $n; ++ $i) {
        $partition[$array[$i]->age & 0xFF][] = &$array[$i];
    }

    $i = 0;

    for($slot = 0; $slot < 256; ++ $slot) {
        for($j = 0, $n = count($partition[$slot]); $j < $n; ++ $j) {
            $array[$i ++] = &$partition[$slot][$j];
        }
    }
    return $array;
}
43
Ja͢ck 2013-06-29 03:05.

安定ソート

次のような配列があるとしましょう。

['Kale', 'Kaleidoscope', 'Aardvark', 'Apple', 'Leicester', 'Lovely']

そして今、あなたは最初の文字だけでソートしたいと思います:

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

結果は次のとおりです。

['Apple', 'Aardvark', 'Kale', 'Kaleidoscope', 'Lovely', 'Leicester']

ソートが安定していませんでした!

熱心な観察者は、配列ソートアルゴリズム(QuickSort)が安定した結果を生成せず、同じ最初の文字の単語間の元の順序が保持されていないことに気付いたかもしれません。このケースは些細なことであり、文字列全体を比較する必要がありますが、ユースケースがより複雑であると仮定しましょう。たとえば、異なるフィールドでの2つの連続したソートは、互いの作業をキャンセルしてはなりません。

シュワルツ変換

シュワルツ変換は、decorate-sort-undecorateイディオムとも呼ばれ、本質的に不安定なソートアルゴリズムを使用して安定したソートを実行します。

まず、各配列要素を、主キー(値)と副キー(そのインデックスまたは位置)で構成される別の配列で装飾します。

array_walk($array, function(&$element, $index) {
    $element = array($element, $index); // decorate
});

これにより、配列が次のように変換されます。

[
    ['Kale', 0], ['Kaleidoscope', 1], 
    ['Aardvark', 2], ['Apple', 3], 
    ['Leicester', 4], ['Lovely', 5]
]

ここで、比較ステップを調整します。最初の文字をもう一度比較しますが、同じ場合は、元の順序を保持するために2番目のキーが使用されます。

usort($array, function($a, $b) {
    // $a[0] and $b[0] contain the primary sort key
    // $a[1] and $b[1] contain the secondary sort key
    $tmp = strcmp($a[0][0], $b[0][0]);

    if ($tmp != 0) {
        return $tmp; // use primary key comparison results
    }

    return $a[1] - $b[1]; // use secondary key
});

その後、装飾を解除します。

array_walk($array, function(&$element) {
    $element = $element[0];
});

最終結果:

['Aardvark', 'Apple', 'Kale', 'Kaleidoscope', 'Leicester', 'Lovely']

再利用はどうですか?

変換された配列要素を操作するには、比較関数を書き直す必要がありました。繊細な比較関数を編集したくない場合があるので、比較関数のラッパーを次に示します。

function stablecmp($fn)
{
    return function($a, $b) use ($fn) {
        if (($tmp = call_user_func($fn, $a[0], $b[0])) != 0) {
            return $tmp;
        } else {
            return $a[1] - $b[1];
        }
    };
}

この関数を使用してソートステップを記述しましょう。

usort($array, stablecmp(function($a, $b) {
    return strcmp($a[0], $b[0]);
}));

出来上がり!手付かずの比較コードが戻ってきました。

15
Orangepill 2013-08-20 09:16.

クロージャ付きのPHP5.3以降、クロージャを使用して並べ替えの順序を決定することもできます。

たとえば、$ arrayがmonthプロパティを含むオブジェクトの配列であると仮定します。

 $orderArray = array("Jan","Feb","Mar","Apr","May","June","July","Aug","Sept","Oct","Nov","Dec");

 usort($array, function($a, $b) use ($orderArray){
       return array_search($a->month, $orderArray) - array_search($b->month, $orderArray);
 }); 
9
Athari 2015-06-04 14:58.

LINQ

.NETでは、LINQは並べ替えに頻繁に使用されます。これにより、特にオブジェクトを複数のフィールドで並べ替える必要がある場合に、比較関数よりもはるかに優れた構文が提供されます。YaLinqoライブラリ*を含む、LINQからPHPへのいくつかのポートがあります。これにより、複雑な比較関数を記述せずに、配列を1行で並べ替えることができます。

$sortedByName         = from($objects)->orderBy('$v->name');
$sortedByCount        = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');

次に、2番目の引数としてコールバックを渡すことにより、比較をさらにカスタマイズできます。

$sortedByFilenameNat  = from($objects)->orderBy('$v->filename', 'strnatcmp');

ここで'$v->count'は、の省略形ですfunction ($v) { return $v->count; }(どちらも使用できます)。これらのメソッドチェーンはイテレータを返します。イテレータは->toArray()、必要に応じて最後に追加することで配列に変換できます。

内部、orderBy及び関連する方法は、(適切な配列の並べ替え関数を呼び出すuasortkrsortmultisortusortなど)。

LINQには、SQLに触発された、フィルタリング、グループ化、結合、集計など、さらに多くのメソッドが含まれています。データベースに依存せずに配列やオブジェクトの複雑な変換を実行する必要がある場合に最適です。

*私が開発しました。詳細と他のLINQポートとの比較については、readmeを参照してください。

3
Andrew Surdu 2018-01-31 09:26.

キー値による多次元ソート

キー値による多次元配列の自然ソートであり、元の順序も保持します(メインキーをシャッフルしないでください)。

function multisortByKeyValue( $k, $arr ) {
    $ids   = array();
    $index = 1;

    foreach ( $arr as $key => $row ) {
        $ids[ $key ] = intval( $row[ $k ] ) . '-' . $index . '-' . $key;
        $index ++;
    }

    natsort( $ids );

    $arr = array_merge( $ids, $arr );

    return $arr;
}

テストケース:

$arr = array(
    'id1' => array(
        'label'    => 'ID 1',
        'priority' => 30,
    ),
    'id2' => array(
        'label'    => 'ID 2',
        'priority' => 70,
    ),
    'id3' => array(
        'label'    => 'ID 3',
        'priority' => 20,
    ),
    'id4' => array(
        'label'    => 'ID 4',
        'priority' => 30,
    ),
);

$sorted = multisortByKeyValue( 'priority', $arr );

// $sorted equals to:
/*
array (
  'id3' => array (
    'label' => 'ID 3',
    'priority' => 20,
  ),
  'id1' => array (
    'label' => 'ID 1',
    'priority' => 30,
  ),
  'id4' => array (
    'label' => 'ID 4',
    'priority' => 30,
  ),
  'id2' => array (
    'label' => 'ID 2',
    'priority' => 70,
  ),
)
*/
2
Ihor Burlachenko 2016-01-16 13:03.

Nsplのsorted関数を使用して配列を並べ替えると非常に便利です

基本的な並べ替え

// Sort array
$sorted = sorted([3, 1, 2]);

// Sort array in descending order
$sortedDesc = sorted([3, 1, 2], true);

関数の結果による並べ替え

// Sort array by the result of a given function (order words by length)
$sortedByLength = sorted(['bc', 'a', 'abc'], 'strlen');
$sortedByLengthDesc = sorted(['bc', 'a', 'abc'], true, 'strlen');

// Sort array by the result of user-defined function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], function($v) { return $v[0]; }); 

// Which is the same as
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], itemGetter(0));
$sortedByTheFirstCharacterDesc = sorted(['bc', 'a', 'abc'], true, itemGetter(0));

// itemGetter(0) returns a function which takes an argument with access by index/key
// and returns the value at index 0

多次元配列の並べ替え

// Sort multidimensional array (sort list of users by their names)
$users = [
    array('name' => 'Robert', 'age' => 20),
    array('name' => 'Alex', 'age' => 30),
    array('name' => 'Jack', 'age' => 25),
];
$sortedByName = sorted($users, itemGetter('name'));
$sortedByNameDesc = sorted($users, true, itemGetter('name'));

// itemGetter('name') returns a function which takes an argument with access by index/key
// and returns the value of the 'name' key

オブジェクトの配列を並べ替える

// Lets assume we have class User(name, age) with properties name and age
// and public methods getName() and getAge()
$users = [
    new User('Robert', 20),
    new User('Alex', 30),
    new User('Jack', 25),
];

// Sort list of objects by property value (sort list of users by their name)
$sortedByName = sorted($users, propertyGetter('name'));
$sortedByNameDesc = sorted($users, true, propertyGetter('name'));

// propertyGetter('name') returns a function which takes an object
// and returns the value of its 'name' property

// Sort list of objects by method result (sort list of users by their age)
$sortedByAge = sorted($users, methodCaller('getAge'));
$sortedByAgeDesc = sorted($users, true, methodCaller('getAge'));

// methodCaller('getAge') returns a function which takes an object
// and returns the result of its getAge() method

比較機能によるソート

// Sort with a comparison function (order words lexicographically with strcmp)
$sortedLexicographically = sorted(['bc', 'a', 'abc'], false, null, 'strcmp');

// Sort with user-defined comparison function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], false, null, function($v1, $v2) {
    return chr($v1[0]) - chr($v2[0]);
});

これらすべての例をここで見ることができます

2
GAV 2019-06-15 07:27.

キー値で注文する場合は、エレガントで明確な1行で注文できます。これは価格の昇順で注文します。array_multisortとarray_columnを使用します。

   Array([0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => coffee [price] => 9.99 ) [2] => Array ( [name] => rice [price] => 4.04 ) )

   array_multisort (array_column($array, 'price'), SORT_ASC, $array);

生産する

     Array ( [0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => rice [price] => 4.04 ) [2] => Array ( [name] => coffee [price] => 9.99 ) )
1
mickmackusa 2019-12-05 01:48.

このページは非常に包括的ですが、宇宙船演算子(3方向比較演算子)のすばらしいユーティリティ(PHP7 +の美しい子)についてもう少し詳しく説明したいと思います。

宇宙船オペレーターを使用して複数のソート条件を実装する

これにより、コードの膨張を減らし、読みやすさを向上させることができます。

複数の条件を処理するカスタムソート(usort()/ uasort()/ uksort())関数を作成する場合は、演算子のいずれかの側にバランスの取れた配列を作成し、結果を返すだけで済みます。ネストされた条件ブロックや複数のリターンはもうありません。

オペレーターの両側の要素は、一度に1つずつ左から右にトラバースされ、同点でない場合、または要素がすべて比較されるとすぐに評価が返されます。

私のデモンストレーションのサンプルデータ:

$multidimArray = [
    'a' => [
        'boolean' => true,
        'natString' => 'text10',
        'object' => (object)['prop' => 2],
        'float' => -.5,
        'mixed' => []
    ],
    'b' => [
        'boolean' => true,
        'natString' => 'text12',
        'object' => (object)['prop' => 4],
        'float' => 0,
        'mixed' => null
    ],
    'c' => [
        'boolean' => false,
        'natString' => 'text100',
        'object' => (object)['prop' => 9],
        'float' => -.5,
        'mixed' => false
    ],
    'd' => [
        'boolean' => true,
        'natString' => 'text1',
        'object' => (object)['prop' => 9],
        'float' => -5,
        'mixed' => "\0"
    ],
    'e' => [
        'boolean' => false,
        'natString' => 'text2',
        'object' => (object)['prop' => 2],
        'float' => .5,
        'mixed' => ''
    ]
];

デモンストレーション(Stackoverflowページの肥大化を回避するには、出力のデモリンクを参照しください):

  • ソートロジック:

    1. ブールDESC(false = 0、true = 1、したがってfalseの前にtrue)
    2. フロートASC

      uasort($multidimArray, function($a, $b) {
          return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']];
      });
      
  • ソートロジック:

    1. 混合ASC
    2. オブジェクトASC
    3. ブールASC

      uasort($multidimArray, function($a, $b) {
          return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']];
      });
      
  • ソートロジック:

    1. オブジェクトASCのプロパティ数
    2. 混合DESCの反復可能性
    3. natStringの長さASC
    4. natString ASC

      uasort($multidimArray, function($a, $b) {
          return [count(get_object_vars($a['object'])), is_iterable($a['mixed']), strlen($a['natString']), $a['natString']]
                 <=>
                 [count(get_object_vars($b['object'])), is_iterable($b['mixed']), strlen($b['natString']), $b['natString']];
      });
      

この構文を使用すると、値、関数の結果、ネストされたデータ、および並べ替え方向をエレガントな方法で並べ替えることができます。これは間違いなくphpツールベルトに入れる価値があります...データベース以外のデータを処理している場合は、もちろんSQLの方がはるかに賢明な手法です。

独自の裁量で、PHP7.4から、これらの無名関数で矢印構文を使用できます。 矢印構文の同じスクリプト

0
Rizerzero 2020-03-06 09:21.

配列を操作するためのより簡単なソリューションが必要な場合は、キーで簡単に並べ替えることができるsortBy関数が実装されているLaravelコレクションパッケージを使用してください。

$collection->sortBy('forename')->sortBy('surname');

つまり、最初にa、次にb、次にcでソートするには、正しい句は次のようになります。

sortBy('c')->sortBy('b')->sortBy('a')

https://packagist.org/packages/tightenco/collect

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

スタートレックの50周年を称えるための最良の方法

スタートレックの50周年を称えるための最良の方法

来年は、スペースオペラの最も壮大で野心的なメディアシリーズの50周年を迎えます。しかし、スタートレックはその誇り高い遺産に沿って50歳の誕生日を迎えますか?スタートレックの誕生日を祝う方法はたくさんあります。

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

(画像提供:ゲッティイメージズ)ドナルド・トランプは、アメリカ合衆国大統領の立候補者となる比類のない外交的洞察力を示し、何百万人もの人々を怒らせ、彼の時代遅れの客体化に対する評価の主要な情報源を失いました。彼が立候補を発表し終える前にパレード。トランプ氏は演説の中で、この国で最も高い役職に選出された場合、米国との南の国境に壁を建設すると述べた一連の声明を発表した。

インターネット上で最も愚かな親ロシアのデマ

インターネット上で最も愚かな親ロシアのデマ

David L. Sternは、ウクライナのキエフを拠点とするフリーランスのライターです。

ディズニーフリークは今、独自の出会い系サイトを持っています

ディズニーフリークは今、独自の出会い系サイトを持っています

オンラインデートに関しては、船長、ベーコン愛好家、ポットヘッド向けに作られたサイトなど、長年にわたって選択できるニッチなサイトがたくさんあります。今、ディズニーファンは彼ら自身のマッチメイキングサイトを通して愛を見つけることができます。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language