it-swarm-eu.dev

Wie sortiere ich ein Array von assoziativen Arrays nach dem Wert eines bestimmten Schlüssels in PHP?

In Anbetracht dieses Arrays:

$inventory = array(

   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),
   array("type"=>"pork", "price"=>5.43),

);

Ich möchte sortiere $inventorys Elemente nach Preis um zu erhalten:

$inventory = array(

   array("type"=>"pork", "price"=>5.43),
   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),

);

Wie kann ich das machen?

344
Matt

Sie haben recht, die gesuchte Funktion ist array_multisort() .

Hier ein Beispiel, das direkt aus dem Handbuch stammt und an Ihren Fall angepasst ist:

$price = array();
foreach ($inventory as $key => $row)
{
    $price[$key] = $row['price'];
}
array_multisort($price, SORT_DESC, $inventory);
482
Josh Davis

PHP 7+

Ab PHP 7 kann dies mit Hilfe von usort mit einer anonymen Funktion , die zum Vergleichen von Elementen den Spaceship-Operator verwendet, präzise ausgeführt werden.

Sie können eine aufsteigende Sortierung wie folgt ausführen:

usort($inventory, function ($item1, $item2) {
    return $item1['price'] <=> $item2['price'];
});

Oder eine absteigende Sorte wie diese:

usort($inventory, function ($item1, $item2) {
    return $item2['price'] <=> $item1['price'];
});

Um zu verstehen, wie das funktioniert, beachten Sie, dass usort eine vom Benutzer bereitgestellte Vergleichsfunktion benötigt, die sich wie folgt verhalten muss (aus den Dokumenten):

Die Vergleichsfunktion muss eine ganze Zahl kleiner, gleich oder größer als Null zurückgeben, wenn das erste Argument als kleiner, gleich oder größer als das zweite betrachtet wird.

Und beachten Sie auch, dass <=>, der Raumschiffoperator,

gibt 0 zurück, wenn beide Operanden gleich sind, 1, wenn links größer ist, und -1, wenn rechts größer ist

genau das braucht usort. Tatsächlich ist fast die gesamte Begründung für das Hinzufügen von <=> zur Sprache in https://wiki.php.net/rfc/combined-comparison-operator das Richtige

erleichtert das Schreiben von Rückrufen für die Bestellung mit usort()


PHP 5.3+

Mit PHP 5.3 wurden anonyme Funktionen eingeführt, der Raumschiffoperator ist jedoch noch nicht verfügbar. Wir können noch usort verwenden, um unser Array zu sortieren, aber es ist etwas ausführlicher und schwieriger zu verstehen:

usort($inventory, function ($item1, $item2) {
    if ($item1['price'] == $item2['price']) return 0;
    return $item1['price'] < $item2['price'] ? -1 : 1;
});

Es ist zwar üblich, dass Komparatoren, die mit ganzzahligen Werten arbeiten, die Differenz der Werte wie $item2['price'] - $item1['price'] zurückgeben, wir können dies jedoch nicht sicher tun. Dies liegt daran, dass die Preise im Beispiel des Fragestellers Fließkommazahlen sind, aber die Vergleichsfunktion, die wir an usort übergeben, muss Ganzzahlen zurückgeben, damit usort ordnungsgemäß funktioniert:

Die Rückgabe von nicht ganzzahligen Werten aus der Vergleichsfunktion, wie beispielsweise float, führt zu einer internen Umwandlung in Ganzzahl des Rückgabewerts des Rückrufs. Werte wie 0,99 und 0,1 werden also in einen ganzzahligen Wert von 0 umgewandelt, der diese Werte als gleich vergleicht.

Dies ist eine wichtige Falle, die bei der Verwendung von usort in PHP 5.x zu beachten ist! Meine ursprüngliche Version dieser Antwort machte diesen Fehler und trotzdem sammelte ich über Tausende von Ansichten zehn Upvotes, offenbar ohne dass jemand den ernsthaften Fehler bemerkte. Mit der Leichtigkeit, mit der fehlende Funktionen wie ich Komparatorfunktionen vermasseln können, ist genau der Grund, warum der benutzerfreundlichere Raumschiff-Operator in PHP 7 zur Sprache hinzugefügt wurde.

231
Mark Amery

Während andere die Verwendung von array_multisort() richtig vorgeschlagen haben, scheint aus irgendeinem Grund keine Antwort die Existenz von array_column() anzuerkennen, was die Lösung erheblich vereinfachen kann. Mein Vorschlag wäre also:

array_multisort(array_column($inventory, 'price'), SORT_DESC, $inventory);
53

Da Ihre Array-Elemente selbst Arrays mit String-Schlüsseln sind, definieren Sie am besten eine benutzerdefinierte Vergleichsfunktion. Das geht ziemlich schnell und einfach. Versuche dies:

function invenDescSort($item1,$item2)
{
    if ($item1['price'] == $item2['price']) return 0;
    return ($item1['price'] < $item2['price']) ? 1 : -1;
}
usort($inventory,'invenDescSort');
print_r($inventory);

Produziert das Folgende:

Array
(
    [0] => Array
        (
            [type] => pork
            [price] => 5.43
        )

    [1] => Array
        (
            [type] => fruit
            [price] => 3.5
        )

    [2] => Array
        (
            [type] => milk
            [price] => 2.9
        )

)
39
zombat

Ich endete damit:

function sort_array_of_array(&$array, $subfield)
{
    $sortarray = array();
    foreach ($array as $key => $row)
    {
        $sortarray[$key] = $row[$subfield];
    }

    array_multisort($sortarray, SORT_ASC, $array);
}

Rufen Sie einfach die Funktion auf und übergeben Sie das Array und den Namen des Felds des Arrays der zweiten Ebene .

sort_array_of_array($inventory, 'price');
21
Danielzt

Sie können usort mit anonymer Funktion verwenden, z.

usort($inventory, function ($a, $b) { return strnatcmp($a['price'], $b['price']); });
13
kenorb
$inventory = 
    array(array("type"=>"fruit", "price"=>3.50),
          array("type"=>"milk", "price"=>2.90),
          array("type"=>"pork", "price"=>5.43),
          );

function pricesort($a, $b) {
  $a = $a['price'];
  $b = $b['price'];
  if ($a == $b)
    return 0;
  return ($a > $b) ? -1 : 1;
}

usort($inventory, "pricesort");
// uksort($inventory, "pricesort");

print("first: ".$inventory[0]['type']."\n\n");
// for usort(): prints milk (item with lowest price)
// for uksort(): prints fruit (item with key 0 in the original $inventory)

// foreach prints the same for usort and uksort.
foreach($inventory as $i){
  print($i['type'].": ".$i['price']."\n");
}

ausgänge:

first: pork

pork: 5.43
fruit: 3.5
milk: 2.9
8
danamlund

Wurde an 100 000 Datensätzen getestet: Zeit in Sekunden (berechnet durch Funkfrequenz) Nur für eindeutige Werte für die Sortierschlüsselpositionen.

Lösung der Funktion von @Josh Davis: Zeitaufwand: 1.5768740177155

Minenlösung: Zeitaufwand: 0,094044923782349

Lösung:

function SortByKeyValue($data, $sortKey, $sort_flags=SORT_ASC)
{
    if (empty($data) or empty($sortKey)) return $data;

    $ordered = array();
    foreach ($data as $key => $value)
        $ordered[$value[$sortKey]] = $value;

    ksort($ordered, $sort_flags);

    return array_values($ordered); *// array_values() added for identical result with multisort*
}
3
Nefelim

Von Sortiere ein Array von assoziativen Arrays nach dem Wert des angegebenen Schlüssels in php :

mit uasort ( http://php.net/uasort ) können Sie ein Array nach Ihrer eigenen definierten Funktion sortieren. In Ihrem Fall ist das einfach:

$array = array(
  array('price'=>'1000.50','product'=>'test1'),
  array('price'=>'8800.50','product'=>'test2'),
  array('price'=>'200.0','product'=>'test3')
);

function cmp($a, $b) {
  return $a['price'] > $b['price'];
}

uasort($array, "cmp");
2
Kamal

Hier ist eine Methode, die ich vor langer Zeit gefunden und ein bisschen aufgeräumt habe. Dies funktioniert hervorragend und kann schnell geändert werden, um auch Objekte zu akzeptieren.

/**
 * A method for sorting arrays by a certain key:value.
 * SortByKey is the key you wish to sort by
 * Direction can be ASC or DESC.
 *
 * @param $array
 * @param $sortByKey
 * @param $sortDirection
 * @return array
 */
private function sortArray($array, $sortByKey, $sortDirection) {

    $sortArray = array();
    $tempArray = array();

    foreach ( $array as $key => $value ) {
        $tempArray[] = strtolower( $value[ $sortByKey ] );
    }

    if($sortDirection=='ASC'){ asort($tempArray ); }
        else{ arsort($tempArray ); }

    foreach ( $tempArray as $key => $temp ){
        $sortArray[] = $array[ $key ];
    }

    return $sortArray;

}

um die Methode zum Sortieren von Objekten zu ändern, ändern Sie einfach die folgende Zeile:

$tempArray[] = strtolower( $value[ $sortByKey ] ); bis $tempArray[] = strtolower( $value->$sortByKey );

Führen Sie die Methode einfach aus

sortArray($inventory,'price','ASC');

1
Kray

Diese Funktion ist wiederverwendbar:

function usortarr(&$array, $key, $callback = 'strnatcasecmp') {
    uasort($array, function($a, $b) use($key, $callback) {
        return call_user_func($callback, $a[$key], $b[$key]);
    });
}

Standardmäßig funktioniert es gut mit Zeichenfolgenwerten, aber Sie müssen den Rückruf für eine Zahlenvergleichsfunktion ausgeben, wenn alle Ihre Zahlen Zahlen sind.

1
mpen

Sie können versuchen, Ihre eigene Vergleichsfunktion zu definieren und dann usort zu verwenden.

1
Alex Sexton
//Just in one line custom function
function cmp($a, $b)
{
return (float) $a['price'] < (float)$b['price'];
}
@uasort($inventory, "cmp");
print_r($inventory);

//result

Array
(
[2] => Array
    (
        [type] => pork
        [price] => 5.43
    )

[0] => Array
    (
        [type] => fruit
        [price] => 3.5
    )

[1] => Array
    (
        [type] => milk
        [price] => 2.9
    )

)
0
Kamal