PHP-Array nach SubArray-Wert sortieren

110

Ich habe die folgende Array-Struktur:

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

Was ist der beste Weg, um das Array inkrementell zu bestellen, basierend auf dem optionNumber?

Die Ergebnisse sehen also so aus:

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
                )
    )
Sjwdavies
quelle

Antworten:

204

Verwenden Sie usort.

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

...

usort($array, "cmp_by_optionNumber");

In PHP ≥5.3 sollten Sie stattdessen eine anonyme Funktion verwenden:

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

Beachten Sie, dass beide oben genannten Codes $a['optionNumber']eine Ganzzahl sind. Verwenden Sie @St. John Johnsons Lösung, wenn es sich um Strings handelt.


Verwenden Sie in PHP ≥7.0 den Raumschiffoperator<=> anstelle der Subtraktion, um Überlauf- / Kürzungsprobleme zu vermeiden.

usort($array, function ($a, $b) {
    return $a['optionNumber'] <=> $b['optionNumber'];
});
kennytm
quelle
1
Das hilft mir nicht wirklich, da Usort erfordert, dass ich ihm eine Funktion zur Verfügung stelle - was das schwierige Stück ist, das ich nicht
verstehen
17
Nun, er hat dir nur die Funktion gegeben, die du benutzen kannst. Und Sie müssen akzeptieren, dass es nicht immer eine eingebaute Funktion gibt, um das zu tun, was Sie wollen. Sie müssen sie selbst schreiben. Vergleichsfunktionen erfordern lediglich eine Rückgabe von 1, 0 oder -1, die die Sortierreihenfolge für zwei Elemente angibt.
Tesserex
1
Ich habe weiter in usort geschaut und es ist eigentlich ziemlich cool. Ich habe eine einfache Vergleichsfunktion mit der obigen geschrieben, jedoch das '==' verpasst. Vielen Dank für die Hilfe Jungs
Sjwdavies
3
Jetzt auch als Abschluss: - usort ($ array, function ($ a, $ b) {return $ b ["optionNumber"] - $ a ["optionNumber"];});
Joeri
1
@ KiloumapL'artélon Wenn das Ergebnis lautet < 0, wird die Sortierfunktion angegeben, die zuvor angezeigt werden asoll b. Wenn es > 0dann ist, bsollte vorher erscheinen a.
Kennytm
57

Verwenden usort

 usort($array, 'sortByOption');
 function sortByOption($a, $b) {
   return strcmp($a['optionNumber'], $b['optionNumber']);
 }
St. John Johnson
quelle
7
@ BenSinclair, das liegt daran, dass Kennys Lösung für Zahlen ist, diese Lösung für Zeichenfolgen. Sie sind beide richtig :-) +1 für diese Alternative.
Kubilay
Verwenden Sie für die Sortierung ohne
Berücksichtigung der
Können wir den Schlüssel für die zweite Ordnung im Array definieren, bedeutet dies, dass wir zuerst mit optionNumber und dann mit lastUpdated sortieren. Wie kann man das machen?
Bhavin Thummar
16

Ich habe beide Lösungen von KennyTM und AJ Quick verwendet und eine Funktion entwickelt, die in diesem Fall in vielen Fällen hilfreich sein kann, z. B. beim Verwenden von ASC- oder DESC- Sortieren oder -Erhalten von Schlüsseln oder wenn Sie Objekte als untergeordnete Elemente eines Arrays haben .

Hier ist diese Funktion (funktioniert für PHP7 und höher aufgrund des Raumschiffoperators):

/**
 * @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;
}

Verwendung:

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

Bearbeiten

Der erste Teil kann mit umgeschrieben werden uasort()und die Funktion wird kürzer (funktioniert für PHP7 und höher aufgrund des Raumschiffoperators):

/**
 * @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;
}
Pigalev Pavel
quelle
Dies ist die beste und nützlichste Antwort hier, sollte oben sein;)
Edi Budimilic
@EdiBudimilic danke, ich schätze es! Übrigens habe ich meine Antwort aktualisiert und eine kürzere Version dieser Funktion hinzugefügt :)
Pigalev Pavel
1
Damit dies für mich funktioniert, musste ich beim Vergleichen und Werten >(größer als) anstelle von -(minus) verwenden, da ich Zeichenfolgen verglichen habe. Funktioniert aber immer noch. $a$b
James
1
@ James du hast recht. Ich habe die Antwort geändert und die Verwendung des Raumschiffoperators (<=>) hinzugefügt. Jetzt sollte es gut funktionieren.
Pigalev Pavel
Gibt es eine Möglichkeit, diesen Fall unempfindlich zu machen?
Loeffel
4

Die Tasten werden entfernt, wenn Sie eine Funktion wie die oben genannten verwenden. Wenn die Schlüssel wichtig sind, würde die folgende Funktion sie beibehalten ... aber foreach-Schleifen sind ziemlich ineffizient.

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

Verwenden Sie arsort anstelle von asort, wenn Sie von hoch nach niedrig möchten.

Code-Gutschrift: http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/

AJ Schnell
quelle
4

Mit array_multisort (), array_map ()

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

print_r($array);

DEMO

Ghanshyam Nakiya
quelle
2
Das funktioniert einfach sehr einfach. Danke dir. Ich musste nur meinen Spaltennamen ändern und es funktionierte.
Kobus Myburgh
2
Dadurch bleiben auch die Schlüssel für das übergeordnete Array erhalten
JonnyS
3

PHP 5.3+

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