PHPで配列とデータをソートするにはどうすればよいですか?


292

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

質問がこの問題の重複としてクローズされた場合は、以下のすべてと著しく異なる理由を説明できる場合にのみ、質問を再度オープンするよう依頼してください。

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


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

  2. SPLによるソート

  3. 安定したソート

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


@jterryまさに、それが私がこれを最終的に閉じるための良い参照質問を持つようにした理由です。それぞれのユニークなスノーフレークに個別に答えることは、誰の助けにもなりません。:)
だます

3
人々は単にphp.netを見てみるべきだと思います
Alexander Jardim

@アレックスハ!もちろんです。問題は、RTFMが誰もいないことです。:D
だます

2
これらの回答はすでにあります。コンテンツを複製(または書き換え)するのではなく、ここで各回答内の最良の回答をリストリンクすることをお勧めします。また、配列は個別に表示される傾向があるため、作品はいずれにせよデュープに反対投票します。
hakre 2013年

1
@deceze:RTFMが誰もいない場合、RTFQAも行われません-既存のQ&A :)
hakre

回答:


164

基本的な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()ため、$aas array('foo' => 'bar', 'baz' => 42)および$bas で呼び出されarray('foo' => ..., 'baz' => ...)ます。次に、関数はusortどちらの値が大きいか、または値が等しいかどうかに戻ります。usort異なる値を渡し、このプロセス繰り返す$a$bアレイがソートされるまでに。cmpこの関数は、何度も呼び出されます少なくとも内の値があるとして何回も$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'];
}

複数のフィールドによる並べ替え

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

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

よく知っている人にとっては、これはを使用したSQLクエリに相当しますORDER BY foo, baz
また、この非常にきちんとした簡略版と、そのような比較関数を任意の数のキーに対して動的に作成する方法も参照してください。

手動の静的な順序へのソート

要素を「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']; });

これが、複雑な多次元配列の並べ替えを簡単にする方法です。繰り返しますが、2つのアイテムのどちらが「大きい」かをPHP教える方法について考えてみてください。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);

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


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


数値比較関数は、float値に対しては機能しません。私はあなたが:)私は何を意味するか知っているんだ
ジャック

1
静的な順序についてはarray_flip()、たとえばの$order[$a['foo']]代わりに、より高速な位置検索を利用するように申請しますarray_search($a['foo'], $order)
ジャック・

少し大きな編集の可能性があります:gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32bですが、それが改善であり、必要なすべてのものが含まれている場合は、それを適用できます。
Rizier123 2016年

@ Rizier123私は確かに努力を称賛します、それは非常に良い記事です。非常に似ていても、別の回答として投稿した方がいいです。リライトには多くの詳細(参照渡し、大きなテーブルなど)が含まれていますが、その詳細は、比較関数であるIMHOの動作のコアトピックへのスムーズな紹介から外れます。マニュアルを意図的に何度か参照していますが、その部分で詳細を調べる必要があるためです。ここで同じことを繰り返して、伝えようとしている中心的な考えから注意をそらす必要はありません。
だます

@decezeこれはリファレンスQ&Aであるため、主な課題は、情報を可能な限りコンパクトで読みやすい形で表示し、ユーザーがソート機能を見つけやすくすることです。私はいくつかのことを微調整:gist.github.com/Rizier123/24a6248758b53245a63e839d8e08a32b別の答えとして、それを投稿するには有用で価値があるならば、それは非常に同様の内容であるので、私はまだ、それについて考える必要がある
Rizier123

139

まあ、ほとんどの基本的な方法はすでにだまし絵でカバーされています。

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;
}

選択ソート

WikipediaのSelection sort記事から

コンピュータサイエンスでは、選択ソートはソートアルゴリズム、具体的にはインプレース比較ソートです。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;
}

シェルソート

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

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

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;
}

コムソート

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

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

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;
}

4
@decezeあなたはすべての基本をカバーしました..私は関連する別の方法を探す必要がありました:)
Baba

5
より学術的な並べ替え方法に問題はないと思います:)ほとんどのアプリケーションではそれほど有用ではありませんが、時々それらが要求される/必要になる場合があるため、特にこれらのほとんどを時間の経過とともに忘れていたため、参照を用意しておくと便利です
Dave

実際には、クイックソートを行うには、最初、中間、最後の要素の3つの値の中央値としてピボットを選択することをお勧めします。これはピボット選択の私の例です。これにより、最悪の場合の逆ソート配列(O(n^2)最初の要素だけをピボットとして使用すると比較が発生します)を回避できます
Alma Do

splは通常の配列ソートよりも速く動作すると聞きましたが、それは正しいですか?
jewelhuq 2016年

私はデイブに同意します。最近では、ほぼfwに含まれているので、それを覚えたり使用したりすることはほとんどありません。
Mike Nguyen

43

安定したソート

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

['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]);
}));

出来上がり!あなたの元の比較コードが戻ってきました。


「本質的に不安定なソートアルゴリズムで安定したソートに影響を与える」というフレーズは、私にとってah-haの瞬間でした。ウィキペディアのページには、「安定」という言葉についての言及がありません。これは、私にとっては変換の美しさのようです。恥。
タイラーコリアー、2015年

1
うん@TylerCollier、あなたはそのウィキペディア参照の行間を読む必要がある...私はあなた;-)そのことの手間保存
ジャック

15

PHP 5.3以降のクロージャーでは、クロージャーを使用してソートの順序を決定することもできます。

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

 $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);
 }); 

これにより、以前の相対的な順序がすべて削除されることを覚えておいてください(たとえば、事前に並べ替えられたリストの最初の「7月」オブジェクトは、並べ替え後、7月オブジェクトのグループの最後になる場合があります)。上記の「安定したソート」を参照してください。
ジョージラングレー

9

LINQ

.NETでは、LINQがソートに頻繁に使用されます。これにより、特にオブジェクトを複数のフィールドでソートする必要がある場合に、比較関数よりも優れた構文が提供されます。YaLinqoライブラリ* を含む、LINQ to 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

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

キー値による多次元配列の自然な並べ替えと元の順序の維持(メインキーをシャッフルしないでください):

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

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

キー値で並べ替える場合は、エレガントでクリアな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

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

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

これにより、コードの膨張と読みやすさの向上に大きく貢献します。

カスタムソート(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

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

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

つまり、最初にa、次にb、次にcの順に並べ替えるには、正しい句は次のようになります。

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

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


-1

配列をソートする方法はいくつかあります。そのtask.fistを実行するためのいくつかの方法について説明します。 '$ numbers'と呼ばれる整数配列を指定します。

$number = array(8,9,3,4,0,1,2);

これは、配列を作成する通常の方法です。その配列を昇順で並べ替えたいとします。そのために、「sort()」メソッドを使用できます。

<?php

    $number = array(8,9,3,4,0,1,2);
    sort($number);

   foreach ($number as $value) {
       echo $value."  ";
   }
?>

次に、その出力を検討します。

ここに画像の説明を入力してください

印刷された数値配列がソートされていることがわかります。その数値配列を降順にしたい場合は、そのタスクに 'rsort()'メソッドを使用できます。

<?php

     $number = array(8,9,3,4,0,1,2);
     rsort($number);

     foreach ($number as $value) {
        echo $value."  ";
     }
?>

出力を検討してください。

ここに画像の説明を入力してください

これで、配列は降順でソートされます。では、連想配列について考えてみましょう。連想配列を与えます(連想配列とは、各インデックスが一意のキー値を持つ配列です)。

$number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);

だから、今、私はこの配列を値に従って昇順でソートしたいと思います。 'asort()'メソッドを使用できます。

<?php

   $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
   asort($number);

   foreach ($number as $value) {
      echo $value."  ";
    }
?>

値に従って降順で並べ替える場合は、 'arsort()'メソッドを使用できます。その配列をキー値に従ってソートしたいとします。この場合、「ksort()」メソッドを使用できます。

<?php

     $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
     ksort($number);

     foreach ($number as $value) {
         echo $value."  ";
     }
?>

次に、出力を検討します。 ここに画像の説明を入力してください

これで、配列はキー値に従って並べ替えられます。キー値に従って配列を降順で並べ替える場合は、 'krsort()'メソッドを使用できます。

<?php

    $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
    krsort($number);

    foreach ($number as $value) {
       echo $value."  ";
    }
?>

これで、連想配列がキー値に従って降順でソートされます。出力を見てください。 ここに画像の説明を入力してください

これらは、phpで配列を昇順または降順で並べ替えるためのいくつかの方法です。私はあなたがアイデアを得ることを願っています。ありがとう!


Decezeはこれらの洞察をすでにカバーしていません:「これらの違いは、Key-Valueの関連付けが維持されるか( "a"関数)、低から高にソートされるか、または逆( "r")にソートされるか、値またはキー( "k")と値の比較方法( "nat"と通常)を並べ替えます。 " 受け入れられた答えで?
mickmackusa

-2

最も簡単なのは、usort関数を使用して、ループせずに配列をソートすることです。以下に例を示します。

   $array_compare= array("0" =>4,"1"=>2,"2"=>500,"3"=>100);

これは降順でソートされます。

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) > 0 ? 1 :-1;
    });

これは昇順でソートされます。

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) < 0 ? 1 :-1;
    });

1
1)サンプルとコードに一貫性がありません。2)これは、すでに上記の回答の耐え難いほど詳細に説明されています。3)別の質問に回答しようとしている可能性がありますか?
落ち着く
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.