Frage

    

Diese Frage bereits eine Antwort hier:

         

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.

War es hilfreich?

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:

  1. Es ist wiederverwendbar . Sie die Sortierspalte als Variable angeben, anstatt es zu hartzucodieren
  2. 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
  3. Es ist reversible . Sie können angeben, dass die Sortierung rückgängig gemacht werden soll - individuell für jede Spalte
  4. 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).
  5. Es ist assoziativ, wenn Sie wollen. Dieser Code übernimmt Sortier Artikel, aber Sie wählen Sie die aktuelle Sortierfunktion (usort oder uasort)
  6. Schließlich ist es nicht array_multisort verwenden: Während array_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'));

Sehen sie in Aktion .

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

Sehen sie in Aktion .

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

Sehen sie in Aktion .

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

Sehen sie in Aktion .

Um nach Nummer absteigend sortieren und dann nach Namen absteigend:

usort($data, make_comparer(['number', SORT_DESC], ['name', SORT_DESC]));

Sehen sie in Aktion .

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

Sehen sie in Aktion .

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

Sehen sie in Aktion .

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

Sehen sie in Aktion .

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 .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top