Wie sortiere ich mehrdimensionale Arrays nach Wert?

1129

Wie kann ich dieses Array nach dem Wert des "order" -Schlüssels sortieren? Obwohl die Werte derzeit sequentiell sind, werden sie nicht immer sequentiell sein.

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
        )
)
stef
quelle
Am schnellsten ist es, das isomorphe Sort-Array- Modul zu verwenden, das sowohl im Browser als auch im Knoten nativ funktioniert und jede Art von Eingabe, berechneten Feldern und benutzerdefinierten Sortierreihenfolgen unterstützt.
Lloyd

Antworten:

1734

Versuchen Sie es mit einem Usort . Wenn Sie noch mit PHP 5.2 oder früher arbeiten, müssen Sie zuerst eine Sortierfunktion definieren:

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

usort($myArray, 'sortByOrder');

Ab PHP 5.3 können Sie eine anonyme Funktion verwenden:

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

Und schließlich können Sie mit PHP 7 den Raumschiff-Operator verwenden :

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

Um dies auf die mehrdimensionale Sortierung auszudehnen, verweisen Sie auf das zweite / dritte Sortierelement, wenn das erste Null ist - am besten unten erläutert. Sie können dies auch zum Sortieren nach Unterelementen verwenden.

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

Wenn Sie Schlüsselzuordnungen beibehalten müssen, verwenden Sie uasort()- siehe Vergleich der Array-Sortierfunktionen im Handbuch

Christian Studer
quelle
2
Meine Phrasierung ist ein bisschen falsch, ich werde sie bearbeiten. Was ich damit gemeint habe ist, dass Sie, wenn Sie nicht mit PHP 5.3 arbeiten, eine spezielle Funktion nur für diese bestimmte Sortierung erstellen müssen (was irgendwie nicht sehr elegant ist). Andernfalls könnten Sie genau dort eine anonyme Funktion verwenden.
Christian Studer
23
@ Jonathan: Sie können die meiste Arbeit, die PHP leistet, nicht wirklich sehen. Es nimmt das Array und beginnt mit zwei Elementen, die es an diese benutzerdefinierte Funktion übergeben hat. Ihre Funktion ist dann dafür verantwortlich, sie zu vergleichen: Wenn das erste Element größer als das zweite ist, geben Sie eine positive Ganzzahl zurück. Wenn es kleiner ist, geben Sie eine negative zurück. Wenn sie gleich sind, geben Sie 0 zurück. PHP sendet dann zwei weitere Elemente an Ihre Funktion und setzt dies fort, bis das Array sortiert wurde. Die Funktion hier ist sehr kurz, es könnte viel komplizierter sein, wenn Sie keine ganzen Zahlen vergleichen würden.
Christian Studer
61
Protip: Verwenden uasort()Sie diese Option, wenn Sie die Array-Schlüssel beibehalten möchten.
thaddeusmt
15
Seien Sie vorsichtig, wenn die sortierbaren Werte Dezimalzahlen sind. Wenn die Sortierfunktion $ a = 1 und $ b = 0,1 erhält, beträgt die Differenz 0,9, aber die Funktion gibt ein int zurück, in diesem Fall 0, sodass $ a und $ b als gleich angesehen und falsch sortiert werden. Es ist zuverlässiger zu vergleichen, ob $ a größer als $ b oder gleich ist, und entsprechend -1, 1 oder 0 zurückzugeben.
Greenlandi
37
Ich habe eine Weile gebraucht, um es herauszufinden. Um die umgekehrte Reihenfolge (DESC) zu sortieren, können Sie $ a und $ b wechseln. Also $ b ['Bestellung'] - $ a ['Bestellung']
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");
o0 '.
quelle
7
@ noc2spam Ich bin froh zu helfen, aber erwäge, dem Vorschlag von studer zu folgen, der wahrscheinlich effizienter und sicherlich ordentlicher ist!
o0 '.
1
@ Lohoris sicher, Alter, ich überprüfe das auch. Gestern wäre ein härterer Tag im Büro gewesen, wenn ich diese Frage nicht gefunden hätte :-)
Gogol
hmm, ich kann keine Antwort hinzufügen. Nun, ich habe es hierher gebracht, weil ich diese dummen Punkte nicht brauche. Für eine mehrdimensionale Sortierung ist es (fast) dasselbe (srry, du musst es kopieren, einfügen und neu formatieren): function aasort (& $ array , $ key1, $ key2, $ key3) {$ sorter = array (); $ ret = array (); zurücksetzen ($ array); foreach ($ array als $ ii => $ va) {$ sorter [$ ii] = getPrice ($ va [$ key1] [$ key2] [$ key3]); } arsort ($ sorter); foreach ($ sorter als $ ii => $ va) {$ ret [$ ii] = $ array [$ ii]; } $ array = $ ret; }
Jaxx0rr
3
Viel einfacher anzuwenden als oben Antwort
Marcel
1
DU BIST TOLL!! WERKE WIE CHARME FÜR PHP 7.2 DANKE
VIEL
270

Ich benutze diese Funktion:

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');
Tom Haigh
quelle
3
Funktioniert sehr gut. Die einzigartige Lösung, die eine Sortierrichtung hinzufügen kann. Vielen Dank!
Ivo Pereira
2
Für eine Alternative, die Sortieranweisungen und viele zusätzliche Funktionen unterstützt, sollten Sie sich meine Antwort hier ansehen - sie hat auch den Vorteil, dass sie nicht verwendet wird array_multisortund daher nicht vorbelegt werden muss $sort_col, was Zeit und Speicher spart .
Jon
Funktioniert gut für mich, aber ... warum muss es angegeben werden, &$arranstatt nur $arr?
Radu Murzea
2
@ RaduMurzea, so dass das Array als Referenz übergeben wird und von der Funktion geändert werden kann, anstatt von der Funktion, die eine Kopie erhält
Tom Haigh
1
@AdrianP. : das Array wird als Referenz übergeben, so dass es das übergebene Array ändert, anstatt eine sortierte Kopie zurückzugeben
Tom Haigh
72

Normalerweise benutze ich usort und übergebe meine eigene Vergleichsfunktion. In diesem Fall ist es sehr einfach:

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

In PHP 7 mit Raumschiffoperator:

usort($array, function($a, $b) {
    return $a['order'] <=> $b['order'];
});
Jan Fabry
quelle
4
Verdammt, ich war 30 Sekunden langsamer. Ist es nicht $ a - $ b?
Christian Studer
3
Ich verstehe das immer falsch. Lassen Sie mich aus dem Handbuch denken: Der Rückgabewert muss kleiner als Null sein, wenn das erste Argument als kleiner als das zweite betrachtet wird. Wenn $a['order']also 3 und $b['order']6 ist, werde ich -3 zurückgeben. Richtig?
Jan Fabry
3
Nun, Sie geben b - a zurück, also wird es 3 sein. Und somit falsch sortiert.
Christian Studer
26
Ah. OK. Ich habe eine nicht logische Arithmetik verwendet, bei der die Idee in Ihrem Kopf nicht mit den von Ihnen produzierten Wörtern übereinstimmt. Dies wird am häufigsten am Freitagnachmittag untersucht.
Jan Fabry
In einigen Fällen ist die obige Antwort ein falsches Ergebnis. Referenz stackoverflow.com/questions/50636981/…
Bilal Ahmed
45

Ein Ansatz, um dies zu erreichen, wäre folgender

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

Ergebnis:

    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
            )

    )
ajuchacko91
quelle
18

Um das Array nach dem Wert des Schlüssels "title" zu sortieren, verwenden Sie:

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

strcmp vergleiche die Strings.

uasort () verwaltet die Array-Schlüssel so, wie sie definiert wurden.

BK
quelle
strcmp ist eine bemerkenswerte Hilfe für Varchar-Typen. Ich mochte diese Antwort kurz und schnell
StudioX
17
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

Dies berücksichtigt sowohl Groß- als auch Kleinbuchstaben.

Nitrodbz
quelle
4
Wie beantwortet dies die Frage der Sortierung nach einem bestimmten Array-Schlüssel?
Seano
12

Verwenden Sie array_multisort(),array_map()

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

print_r($array);

DEMO

Ghanshyam Nakiya
quelle
Beachten Sie, dass bei diesem Ansatz eine Benachrichtigung ausgegeben wird. array_multisortverweist auf den ersten Parameter.
Kami Yang
5

Der flexibelste Ansatz wäre die Verwendung dieser Methode

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

hier ist der Grund:

  • Sie können nach jedem Schlüssel sortieren (auch verschachtelt wie 'key1.key2.key3'oder ['k1', 'k2', 'k3'])

  • Funktioniert sowohl für assoziative als auch für nicht assoziative Arrays ( $assocFlag)

  • Es wird keine Referenz verwendet - neues sortiertes Array zurückgeben

In Ihrem Fall wäre es so einfach wie:

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

Diese Methode ist Teil dieser Bibliothek .

Minwork
quelle
1

Seien wir ehrlich: PHP verfügt NICHT über eine einfache Out-of-the-Box-Funktion, um jedes Array-Sortierszenario richtig zu handhaben.

Diese Routine ist intuitiv, was ein schnelleres Debuggen und eine schnellere Wartung bedeutet:

// 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);
    }
}
Tony Gil
quelle
4
"Seien wir ehrlich: PHP verfügt NICHT über eine einfache Out-of-the-Box-Funktion, um jedes Array-Sortierszenario richtig zu handhaben." Genau dafür sind usort / ksort / asort konzipiert ^^ '
Ben Cassinat
3
Tatsächlich verfügt PHP über viele Sortierfunktionen , mit denen jedes Array-Sortierszenario behandelt werden kann.
Axiac
In Bezug auf Debugging und Wartung ist die Verwendung von globaleine große rote Fahne und wird im Allgemeinen nicht empfohlen . Warum wird mysql_fetch_arrayfür diese Frage anstelle des Quellarrays des OP demonstriert, und es gibt keine Erklärung dafür, was Ihr Code tut und was das Ergebnis erwarten kann? Insgesamt ist dies ein sehr komplexer Ansatz, um das gewünschte Endergebnis zu erzielen.
Fyrye
@tonygil Ich kann anhand Ihrer Antwort und des Datensatzes des OP nicht feststellen, welche Ergebnisse Sie erwarten. Es mag für Sie offensichtlich sein, aber ich weiß nicht, wie Ihre Antwort die Frage des OP beantwortet. Sie können jedoch eine Referenz übergeben, anstatt globalsee: 3v4l.org/FEeFC zu verwenden. Dies erzeugt eine explizit definierte Variable und keine, auf die global geändert und zugegriffen werden kann.
Fyrye
0

Sie können mehrdimensionale Arrays auch nach mehreren Werten wie as sortieren

$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"
    ],

];

mit

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

Ausgabe mit 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) Die Verwendung von strcmp wäre eine gute Option, um die Zeichenfolgen zu vergleichen.

StudioX
quelle