Mehrdimensionale Arrays in PHP bequem sortieren

Für das Sortieren von Arrays bringt PHP mit sort, rsort, etc. viele Funktionen mit. Auch für assoziative Arrays stehen jede Menge Sortierfunktionen bereit. Manchmal möchte man jedoch mehrdimensionale Arrays sortieren und das möglichst bequem.

Zum Sortieren mehrdimensionaler Arrays stellt uns PHP die Funktion array_multisort zur Verfügung. Ich möchte nun an einem Beispiel zeigen, wie man mehrdimensionale Arrays mit dieser Funktion sortiert. Zum Sortieren brauchen wir natürlich ein paar Beispieldaten.

Jahrgang Nachname Vorname
1979 Müller Annegret
1983 Schmidt Lisbeth
1980 Meier Günther
1981 Werner Gabi
1980 Hofmann Ramona
1981 Kaufmann Maria

Als Array definiert sieht das dann so aus:

$data = array(
    array("jahrgang" => 1979, "nachname" => "Müller",   "vorname" => "Annegret"),
    array("jahrgang" => 1983, "nachname" => "Schmidt",  "vorname" => "Lisbeth"),
    array("jahrgang" => 1980, "nachname" => "Meier",    "vorname" => "Günther"),
    array("jahrgang" => 1981, "nachname" => "Werner",   "vorname" => "Gabi"),
    array("jahrgang" => 1980, "nachname" => "Hofmann",  "vorname" => "Ramona"),
    array("jahrgang" => 1981, "nachname" => "Kaufmann", "vorname" => "Maria"),
);
 

Jetzt wollen wir unsere Daten sortieren, und zwar absteigend nach Jahrgang und aufsteigend nach dem Nachnamen. Leider können wir unseren Wunsch array_multisort so nicht übergeben. Es ist etwas Vorarbeit nötig.

Gemeinerweise benötigt array_multisort ein Array von Spalten, wir aber haben ein Array von Zeilen. Folglich müssen wir erst die relevanten Spalten extrahieren.

foreach ($data as $key => $row) {
    $jahrgang[$key] = $row['jahrgang'];
    $nachname[$key] = $row['nachname'];
}
 

Jetzt können wir endlich sortieren.

array_multisort($jahrgang, SORT_DESC, $nachname, SORT_ASC, SORT_STRING, $data);
 

Richtig schön wird es aber eigentlich erst, wenn wir uns das Extrahieren der Spalten sparen könnten und lediglich sagen müßten, wie wir unsere Daten sortiert haben wollen. Das ist überhaupt kein Problem, denn für wiederkehrende Aufgaben haben wir schließlich Computer.

Für diese wiederkehrende Aufgabe habe ich mir die Funktion sortArrayByFields geschrieben.

function sortArrayByFields($arr, $fields)
{
    $sortFields = array();
    $args       = array();

    foreach ($arr as $key => $row) {
        foreach ($fields as $field => $order) {
            $sortFields[$field][$key] = $row[$field];
        }
    }

    foreach ($fields as $field => $order) {
        $args[] = $sortFields[$field];

        if (is_array($order)) {
            foreach ($order as $pt) {
                $args[$pt];
            }
        } else {
            $args[] = $order;
        }
    }

    $args[] = &$arr;

    call_user_func_array('array_multisort', $args);

    return $arr;
}
 

Um obiges Ergebnis zu erhalten, braucht es jetzt nur noch eine Anweisung.

$sorted = sortArrayByFields(
    $data,
    array(
        'jahrgang' => SORT_DESC,
        'nachname' => array(SORT_ASC, SORT_STRING)
    )
);
 

Mit sortArrayByFields lassen sich nun mehrdimensionale Arrays bequem sortieren.

Tags:

6 Kommentare zu “Mehrdimensionale Arrays in PHP bequem sortieren”

  1. Thomas Schmidt 2. Juni 2015 at 20:22 #

    Hallo,

    genau sowas hatte ich schon lange gesucht… Vielen vielen Dank für die Funktion.

    Ein kleines Problem habe ich aber. Fängt ein Begriff mit klein-Buchstaben (zum Bsp. k….) an, werden die nach Z…. sortiert.

    Ich habe jetzt einfach in der Zeile 7:

    $sortFields[$field][$key] = $row[$field];

    in

    $sortFields[$field][$key] = strtolower($row[$field]);

    geändert. Jetzt funktioniert es wie gewollt.
    Meine Frage…. Kann es deswegen zu unerwartete Ergebnisse führen, wenn ich nicht (nur) mit SORT_ASC bzw. SORT_DESC sortiere?

    Mfg Thomas

    • scheddel 2. Juni 2015 at 20:32 #

      Unerwartete Ergebnisse sollte es nicht geben. Wenn man nicht zwischen Groß- und Kleinschreibung unterscheiden möchte, gibt es ab der PHP Version 5.4. auch noch das Flag SORT_FLAG_CASE.

  2. Flo 27. August 2015 at 15:22 #

    Unter PHP Version 5.3.3 bekomme ich bei deiner – unter 5.2.8 noch tadellos laufenden – Funktion folgendes:

    Warning: call_user_func_array() expects parameter 2 to be array, null given in ….

    für die Zeile

    call_user_func_array(‚array_multisort‘, $args);

    Wenn ich nur die Referenz von $args übergebe, ändert das nichts … eine Idee? Bin grad mit dem Latein etwas am Ende.

  3. Flo 27. August 2015 at 15:23 #

    Sorry, die Meldung lautet natürlich:

    „Warning: Parameter 1 to array_multisort() expected to be a reference, value given in“

  4. Jürgen 15. April 2016 at 10:17 #

    Hallo,
    sehr gut, das, was ich gesucht hatte.

    ABER nicht ganz fehlerfrei.

    Wenn ich im obigen Beispiel die Zeile für die zweite Sortierung

    ’nachname‘ => array(SORT_ASC, SORT_STRING)

    in

    ’nachname‘ => array(SORT_DESC, SORT_STRING)

    ändere, ändert sich die Reihenfolge zwischen Hoffman und Meier nicht

    Gruß
    Jürgen

  5. Karsten 3. November 2016 at 20:32 #

    Hallo,

    mit der Angabe

    ’nachname => [SORT_ASC,SORT_STRING]

    gabs bei $args[$pt]; ein notice und sortierte nicht richtig,

    Ich habe folgende geändert

    foreach ($order as $pt) {
    $args[] = $pt;
    }

    und es funktioniert wunderbar und die Sortierungen stimmen,
    auch bei Angaben wie

    array(
    ’nachname => [SORT_ASC,SORT_STRING],
    ‚vorname => [SORT_ASC,SORT_STRING],
    )

    Schöne Grüße

    Karsten

Schreib einen Kommentar!