Wie kann ich ein mehrdimensionales Array in PHP sortieren [Duplicate]
-
01-07-2019 - |
Frage
Diese Frage bereits eine Antwort hier:
- Wie kann ich Array und Daten in PHP sortieren? 10 Antworten
Ich habe CSV-Daten in ein mehrdimensionales Array geladen. Auf diese Weise wird jede „Reihe“ ist ein Datensatz, und jede „Spalte“ enthält die gleiche Art von Daten. Ich verwende die Funktion unten auf meine CSV-Datei zu laden.
function f_parse_csv($file, $longest, $delimiter)
{
$mdarray = array();
$file = fopen($file, "r");
while ($line = fgetcsv($file, $longest, $delimiter))
{
array_push($mdarray, $line);
}
fclose($file);
return $mdarray;
}
Ich brauche eine Spalte angeben zu können, so sortieren, dass sie die Reihen umlagern. Eine der Spalten enthält aktuelle Informationen im Format von Y-m-d H:i:s
und ich möchte mit dem jüngsten Datum wobei die erste Reihe sortieren können.
Lösung
Sie können mit array_multisort ()
Versuchen Sie etwas wie folgt aus:
foreach ($mdarray as $key => $row) {
// replace 0 with the field's index/key
$dates[$key] = $row[0];
}
array_multisort($dates, SORT_DESC, $mdarray);
Für PHP> = 5.5.0 extrahieren nur die Spalte von zu sortieren. Keine Notwendigkeit für die Schleife:
array_multisort(array_column($mdarray, 0), SORT_DESC, $mdarray);
Andere Tipps
Einführung: eine sehr verallgemeinerte Lösung für PHP 5.3 +
Ich möchte meine eigene Lösung hier hinzufügen, da sie bietet Features, die andere Antworten nicht.
Im Einzelnen Vorteile dieser Lösung sind:
- Es ist wiederverwendbar . Sie die Sortierspalte als Variable angeben, anstatt es zu hartzucodieren
- Es ist flexibel . Sie mehrere Sortierspalten (so viele, wie Sie wollen) angeben können - zusätzliche Spalten werden als Tiebreaker zwischen Elementen verwendet, die anfänglich gleich vergleichen
- Es ist reversible . Sie können angeben, dass die Sortierung rückgängig gemacht werden soll - individuell für jede Spalte
- Es ist erweiterbare : Wenn der Datensatz Spalten enthält, die nicht in einem „dummen“ Art und Weise verglichen werden können (zB Datum Strings) können Sie auch festlegen, wie diese Elemente auf einen Wert konvertieren, die direkt sein kann verglichen (zB
DateTime
Beispiel). - Es ist assoziativ, wenn Sie wollen. Dieser Code übernimmt Sortier Artikel, aber Sie wählen Sie die aktuelle Sortierfunktion (
usort
oderuasort
) - Schließlich ist es nicht
array_multisort
verwenden: Währendarray_multisort
bequem ist, hängt es vor dem Sortieren eine Projektion aller Eingabedaten über das Erstellen. Dies kostet Zeit und Speicher und kann einfach unerschwinglich sein, wenn Ihr Datensatz ist groß.
Der Code
function make_comparer() {
// Normalize criteria up front so that the comparer finds everything tidy
$criteria = func_get_args();
foreach ($criteria as $index => $criterion) {
$criteria[$index] = is_array($criterion)
? array_pad($criterion, 3, null)
: array($criterion, SORT_ASC, null);
}
return function($first, $second) use (&$criteria) {
foreach ($criteria as $criterion) {
// How will we compare this round?
list($column, $sortOrder, $projection) = $criterion;
$sortOrder = $sortOrder === SORT_DESC ? -1 : 1;
// If a projection was defined project the values now
if ($projection) {
$lhs = call_user_func($projection, $first[$column]);
$rhs = call_user_func($projection, $second[$column]);
}
else {
$lhs = $first[$column];
$rhs = $second[$column];
}
// Do the actual comparison; do not return if equal
if ($lhs < $rhs) {
return -1 * $sortOrder;
}
else if ($lhs > $rhs) {
return 1 * $sortOrder;
}
}
return 0; // tiebreakers exhausted, so $first == $second
};
}
Wie verwenden
In diesem Abschnitt werde ich Links, die von dieser Probe Datensatz sortieren:
$data = array(
array('zz', 'name' => 'Jack', 'number' => 22, 'birthday' => '12/03/1980'),
array('xx', 'name' => 'Adam', 'number' => 16, 'birthday' => '01/12/1979'),
array('aa', 'name' => 'Paul', 'number' => 16, 'birthday' => '03/11/1987'),
array('cc', 'name' => 'Helen', 'number' => 44, 'birthday' => '24/06/1967'),
);
Die Grundlagen
Die Funktion make_comparer
akzeptiert eine variable Anzahl von Argumenten, die die gewünschte Art und gibt eine Funktion definieren, die Sie sollen als Argument verwenden, um usort
oder uasort
.
Der einfachste Anwendungsfall im Schlüssel zu übergeben ist, dass Sie ‚verwenden möchten Datenelemente zu vergleichen. Zum Beispiel durch die $data
Artikel zu sortieren name
Sie tun würden,
usort($data, make_comparer('name'));
Der Schlüssel kann auch eine Zahl sein, wenn die Elemente numerisch indizierte Arrays sind. Für das Beispiel in der Frage, wäre dies
usort($data, make_comparer(0)); // 0 = first numerically indexed column
Mehrere Sortierspalten
Sie können, indem zusätzliche Parameter mehrere Sortier Spalten angeben make_comparer
. Zum Beispiel durch „Nummer“ zu sortieren und dann durch die Null-indexierte Spalte:
usort($data, make_comparer('number', 0));
Erweiterte Funktionen
Erweiterte Funktionen stehen zur Verfügung, wenn Sie eine Sortierspalte als ein Array angeben, anstelle einer einfachen Zeichenfolge. Dieses Array sollte numerisch indiziert werden, und müssen diese Elemente enthalten:
0 => the column name to sort on (mandatory)
1 => either SORT_ASC or SORT_DESC (optional)
2 => a projection function (optional)
Lassen Sie uns sehen, wie wir diese Funktionen nutzen können.
Sortierung umkehren
So sortiert nach Namen absteigend:
usort($data, make_comparer(['name', SORT_DESC]));
Um nach Nummer absteigend sortieren und dann nach Namen absteigend:
usort($data, make_comparer(['number', SORT_DESC], ['name', SORT_DESC]));
Benutzerdefinierte Projektionen
In einigen Fällen können Sie durch eine Spalte, deren Werte sortieren müssen verleihen nicht gut zu sortieren. Die „Geburtstag“ Spalte in dem Beispieldatensatz paßt diese Beschreibung: es keinen Sinn macht, Geburtstage als Zeichenfolge vergleichen (weil zum Beispiel „01/01/1980“ kommt vor „1970.10.10“). In diesem Fall wollen wir angeben, wie auf Projekt die tatsächlichen Daten in eine Form, die kann mit der gewünschten Semantik direkt miteinander verglichen werden.
Die Projektionen können als jede Art von aufrufbar angegeben werden: als Strings, Arrays oder anonym Funktionen. Ein Vorsprung wird angenommen, ein Argument zu akzeptieren und Return seiner angenommenen Form.
Es ist zu beachten, dass, während Vorsprünge ähnlich den benutzerdefinierten Vergleichsfunktionen mit usort
und Familie eingesetzt sind, sind sie einfacher (man braucht nur einen Wert in ein anderes zu konvertieren) und nutzen die gesamte Funktionalität bereits gebacken in make_comparer
.
Lassen Sie uns die Beispieldaten ohne Projektion gesetzt sortieren und sehen, was passiert:
usort($data, make_comparer('birthday'));
Das war nicht das gewünschte Ergebnis. Aber wir können benutzen date_create
als Projektion:
usort($data, make_comparer(['birthday', SORT_ASC, 'date_create']));
Dies ist die richtige Reihenfolge, dass wir wollten.
Es gibt viele weitere Dinge, die Projektionen erreichen können. Zum Beispiel kann eine schnelle Möglichkeit, eine Groß- und Kleinschreibung Art zu bekommen, ist strtolower
als Projektion zu verwenden.
Das heißt, ich sollte auch erwähnen, dass es besser ist, keine Projektionen zu verwenden, wenn die Datenmenge ist groß: In diesem Fall wäre es viel schneller sein, alle manuell vorne um Ihre Daten zu projizieren und dann sortieren, ohne eine Projektion, obwohl tun so wird eine erhöhte Speichernutzung für eine schnellere Sortiergeschwindigkeit handeln.
Schließlich, hier ist ein Beispiel, das alle Funktionen verwendet: zunächst sortiert nach Anzahl absteigend, dann durch Geburtstag aufsteigend:
usort($data, make_comparer(
['number', SORT_DESC],
['birthday', SORT_ASC, 'date_create']
));
Mit usort . Hier ist eine generische Lösung, die Sie für verschiedene Spalten verwenden können:
class TableSorter {
protected $column;
function __construct($column) {
$this->column = $column;
}
function sort($table) {
usort($table, array($this, 'compare'));
return $table;
}
function compare($a, $b) {
if ($a[$this->column] == $b[$this->column]) {
return 0;
}
return ($a[$this->column] < $b[$this->column]) ? -1 : 1;
}
}
So sortieren nach ersten Spalte:
$sorter = new TableSorter(0); // sort by first column
$mdarray = $sorter->sort($mdarray);
Mehrere Reihe mit einer Verschlusssortierung
Hier ist ein weiterer Ansatz uasort () und eine anonyme Callback-Funktion (Schließen). Ich habe diese Funktion regelmäßig verwendet. PHP 5.3 erforderlich - nicht mehr Abhängigkeiten
!/**
* Sorting array of associative arrays - multiple row sorting using a closure.
* See also: http://the-art-of-web.com/php/sortarray/
*
* @param array $data input-array
* @param string|array $fields array-keys
* @license Public Domain
* @return array
*/
function sortArray( $data, $field ) {
$field = (array) $field;
uasort( $data, function($a, $b) use($field) {
$retval = 0;
foreach( $field as $fieldname ) {
if( $retval == 0 ) $retval = strnatcmp( $a[$fieldname], $b[$fieldname] );
}
return $retval;
} );
return $data;
}
/* example */
$data = array(
array( "firstname" => "Mary", "lastname" => "Johnson", "age" => 25 ),
array( "firstname" => "Amanda", "lastname" => "Miller", "age" => 18 ),
array( "firstname" => "James", "lastname" => "Brown", "age" => 31 ),
array( "firstname" => "Patricia", "lastname" => "Williams", "age" => 7 ),
array( "firstname" => "Michael", "lastname" => "Davis", "age" => 43 ),
array( "firstname" => "Sarah", "lastname" => "Miller", "age" => 24 ),
array( "firstname" => "Patrick", "lastname" => "Miller", "age" => 27 )
);
$data = sortArray( $data, 'age' );
$data = sortArray( $data, array( 'lastname', 'firstname' ) );
Ich weiß, dass es 2 Jahre ist, da diese Frage gestellt und beantwortet wurde, aber hier ist eine andere Funktion, die ein zweidimensionales Feld sortiert. Er akzeptiert eine variable Anzahl von Argumenten, so dass Sie in mehr als ein Schlüssel (dh Spaltenname) zu sortieren, passieren. PHP 5.3 erforderlich.
function sort_multi_array ($array, $key)
{
$keys = array();
for ($i=1;$i<func_num_args();$i++) {
$keys[$i-1] = func_get_arg($i);
}
// create a custom search function to pass to usort
$func = function ($a, $b) use ($keys) {
for ($i=0;$i<count($keys);$i++) {
if ($a[$keys[$i]] != $b[$keys[$i]]) {
return ($a[$keys[$i]] < $b[$keys[$i]]) ? -1 : 1;
}
}
return 0;
};
usort($array, $func);
return $array;
}
Versuchen Sie es hier: http://www.exorithm.com/algorithm/view/sort_multi_array
function cmp($a, $b)
{
$p1 = $a['price'];
$p2 = $b['price'];
return (float)$p1 > (float)$p2;
}
uasort($my_array, "cmp");
http://qaify.com/sort-an-array-of-associative-arrays-by-value-of-given-key-in-php/
Die "usort" -Funktion ist die Antwort.
http://php.net/usort
Hier ist eine PHP4 / PHP5-Klasse, die ein oder mehr Felder sortieren:
// a sorter class
// php4 and php5 compatible
class Sorter {
var $sort_fields;
var $backwards = false;
var $numeric = false;
function sort() {
$args = func_get_args();
$array = $args[0];
if (!$array) return array();
$this->sort_fields = array_slice($args, 1);
if (!$this->sort_fields) return $array();
if ($this->numeric) {
usort($array, array($this, 'numericCompare'));
} else {
usort($array, array($this, 'stringCompare'));
}
return $array;
}
function numericCompare($a, $b) {
foreach($this->sort_fields as $sort_field) {
if ($a[$sort_field] == $b[$sort_field]) {
continue;
}
return ($a[$sort_field] < $b[$sort_field]) ? ($this->backwards ? 1 : -1) : ($this->backwards ? -1 : 1);
}
return 0;
}
function stringCompare($a, $b) {
foreach($this->sort_fields as $sort_field) {
$cmp_result = strcasecmp($a[$sort_field], $b[$sort_field]);
if ($cmp_result == 0) continue;
return ($this->backwards ? -$cmp_result : $cmp_result);
}
return 0;
}
}
/////////////////////
// usage examples
// some starting data
$start_data = array(
array('first_name' => 'John', 'last_name' => 'Smith', 'age' => 10),
array('first_name' => 'Joe', 'last_name' => 'Smith', 'age' => 11),
array('first_name' => 'Jake', 'last_name' => 'Xample', 'age' => 9),
);
// sort by last_name, then first_name
$sorter = new Sorter();
print_r($sorter->sort($start_data, 'last_name', 'first_name'));
// sort by first_name, then last_name
$sorter = new Sorter();
print_r($sorter->sort($start_data, 'first_name', 'last_name'));
// sort by last_name, then first_name (backwards)
$sorter = new Sorter();
$sorter->backwards = true;
print_r($sorter->sort($start_data, 'last_name', 'first_name'));
// sort numerically by age
$sorter = new Sorter();
$sorter->numeric = true;
print_r($sorter->sort($start_data, 'age'));
Bevor ich die Tablesorter Klasse bekommen konnte zu laufen hatte, kam ich mit einer Funktion bis auf das, was Shinhan zur Verfügung gestellt hatte.
function sort2d_bycolumn($array, $column, $method, $has_header)
{
if ($has_header) $header = array_shift($array);
foreach ($array as $key => $row) {
$narray[$key] = $row[$column];
}
array_multisort($narray, $method, $array);
if ($has_header) array_unshift($array, $header);
return $array;
}
- $ Array ist das MD-Array Sie sortieren möchten.
- $ Spalte ist die Spalte, die Sie möchten, sortieren durch.
- $ Methode ist, wie Sie die Sortierung durchgeführt möchten, wie SORT_DESC
- $ has_header auf true gesetzt ist, wenn die erste Zeile Header-Werte enthält, die Sie nicht sortiert werden sollen.
Ich habe versucht, mehr populären array_multisort () und usort () Antworten und keiner von ihnen arbeitete für mich. Die Daten nur werden purzeln und der Code ist nicht lesbar. Hier ist eine schnelle eine schmutzige Lösung. WARNUNG: Nur diese verwenden, wenn Sie sicher sind, dass ein vermeintlicher Begrenzer werden Sie nicht wieder kommt später zu verfolgen!
Nehmen wir an, jede Zeile in Ihrem Multi-Array wie folgt aussieht: Name, stuff1, stuff2:
// Sort by name, pull the other stuff along for the ride
foreach ($names_stuff as $name_stuff) {
// To sort by stuff1, that would be first in the contatenation
$sorted_names[] = $name_stuff[0] .','. name_stuff[1] .','. $name_stuff[2];
}
sort($sorted_names, SORT_STRING);
Müssen Sie Ihre Sachen wieder in alphabetischer Reihenfolge?
foreach ($sorted_names as $sorted_name) {
$name_stuff = explode(',',$sorted_name);
// use your $name_stuff[0]
// use your $name_stuff[1]
// ...
}
Ja, es ist schmutzig. Aber super einfach, in Zukunft nicht machen Sie Ihren Kopf explodiert.
Ich ziehe array_multisort zu verwenden. Lesen Sie die Dokumentation hier .