Maresa P.: Mehrdimensionales Array nach Wert sortieren

Hallo liebes Forum,

ich möchte folgendes PHP Array sortieren:

$array[0]['name'] = 'Hans';
$array[0]['street'] = 'Beliebigestraße';
$array[1]['name'] = 'Peter';
$array[1]['street'] = 'Beispielstraße';
$array[2]['name'] = 'Bernd';
$array[2]['street'] = 'Musterstraße';
$array[3]['name'] = 'Gerhard';
$array[3]['street'] = 'Teststraße';

Das Array soll alphabetisch nach 'name' sortiert werden.

Bei einer Ausgabe des sortierten Arrays soll also folgendes herauskommen:

for($key = 0; $key < count($array); $key++) {

echo $array[$key]['name'].' - ';
   echo $array[$key]['street'].'<br>';
}

// soll ergeben
// Bernd - Musterstraße
// Gerhard - Teststraße
// Hans - Beliebigestraße
// Peter - Beispielstraße

a) Muss ich hierzu den Aufbau des Arrays verändern ('name
' wird zum Schlüssel)?
b) Hilf mir hier evtl die Funktion array_multisort() weiter
c) Wie kann ich das realisieren? Könnt Ihr mir helfen?

Vielen Dank und Gruß
Maresa

  1. Hello,

    $array[0]['name'] = 'Hans';
    $array[0]['street'] = 'Beliebigestraße';
    $array[1]['name'] = 'Peter';
    $array[1]['street'] = 'Beispielstraße';
    $array[2]['name'] = 'Bernd';
    $array[2]['street'] = 'Musterstraße';
    $array[3]['name'] = 'Gerhard';
    $array[3]['street'] = 'Teststraße';

    Muss das Array so aussehen, oder könnte es auch

    $array['name'][0]   = 'Hans';
     $array['name'][1]   = 'Peter';
     $array['street'][0] = 'Beliebigestraße';
     $array['street'][1] = 'Beispielstraße';

    so herum aufgebaut werden?

    Du hast nämlich eine reine Spaltenstruktur und die kann man auch in obiger Form abbilden.
    Das macht zwar eigene Funktionen zum Einfügen und Löschen von Elementen notwendig, die sind aber "Peanuts" gegenüber dem Sortieraufwand, den Du Dir sparst...

    Das vorliegende "Array" kannst Du nämlich gleichzeitig nach _jeder_ Spalte sortiert vorhalten.
    Das ist enorm praktisch.

    Grüße vom Berg
    http://www.annerschbarrich.de

    1. hi,

      Du hast nämlich eine reine Spaltenstruktur und die kann man auch in obiger Form abbilden.

      Das halte ich für eher ungünstig.

      Das macht zwar eigene Funktionen zum Einfügen und Löschen von Elementen notwendig,

      Eben.

      die sind aber "Peanuts" gegenüber dem Sortieraufwand, den Du Dir sparst...

      Neben lulus Vorschlag wäre auch noch usort() ein sehr simpler Weg, die Aufgabe zu lösen.

      gruß,
      wahsaga

      --
      /voodoo.css:
      #GeorgeWBush { position:absolute; bottom:-6ft; }
      1. Hello,

        Neben lulus Vorschlag wäre auch noch usort() ein sehr simpler Weg, die Aufgabe zu lösen.

        Da hast Du mich nicht verstanden.
        Ein "Zeilenarray" kann man immer nur nach einer "Spalte" gleichzeitig sortiert halten.
        Es ist daher manchmal günstiger, die Zeilenstruktur in eine Spaltenstruktur umzubauen.

        Lohnt sich natürlich nur, wenn man wirklich mehrere Sortierungen benötigt, um z.B. pro Spalte ein sortiertes Select zu füttern.

        Harzliche Grüße vom Berg
        http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau

        1. hi,

          Da hast Du mich nicht verstanden.

          Doch, ich denke schon.

          Ein "Zeilenarray" kann man immer nur nach einer "Spalte" gleichzeitig sortiert halten.
          Es ist daher manchmal günstiger, die Zeilenstruktur in eine Spaltenstruktur umzubauen.

          Lohnt sich natürlich nur, wenn man wirklich mehrere Sortierungen benötigt

          Würde ich auch _nur_ dann u.U. für gerechtfertigt halten - denn wie du schon sagtest, ist durch deine Transformation das Einfügen/Löschen mit zusätzlichem Aufwand verbunden.

          Außerdem weiß ich noch nicht, mit _welcher_ Funktion du dein Array mit möglichst wenig Aufwand sortieren willst - ohne dass die Zusammenhänge auseinandergerissen werden.

          gruß,
          wahsaga

          --
          /voodoo.css:
          #GeorgeWBush { position:absolute; bottom:-6ft; }
          1. Hello,

            Außerdem weiß ich noch nicht, mit _welcher_ Funktion du dein Array mit möglichst wenig Aufwand sortieren willst - ohne dass die Zusammenhänge auseinandergerissen werden.

            Den gesamtem benötigten Funktionssatz (univesell verwendbar) habe ich hier schon mal hinterlassen.
            Das Sortieren geht natürlich mit jeder PHP-Array-Funktion, die die Schlüssel nicht verändert.
            Denn wie Du ja weißt, sind PHP's Arrays als Bäume aufgebaut, und da werden nicht die Positionen in der Speicherstruktur, sondern nur die Referenzen (Zeiger) von einem zum anderen Element verändert.

            http://forum.de.selfhtml.org/archiv/2005/3/t102531/#m630684

            und weitere mit der Suche: "author:Tom Spaltenarry"

            Das sit aber nur ein Auszug aus dem gesamten Traktat. Wenn es Dich interessiert, suche ich es mal raus aus meinem Festplattengewirr. Die resultierenden Funktionen sind enorm schlank und leicht verständlich.

            Harzliche Grüße vom Berg
            http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau

            1. hi,

              Das Sortieren geht natürlich mit jeder PHP-Array-Funktion, die die Schlüssel nicht verändert.

              Wenn ich jetzt also

              $data['name'] = array('Hans', 'Olaf', 'Adam');
              $data['alter'] = array(32, 47, 21);

              habe - wie soll ich das mit einer vorhandenen PHP-Array-Funktion sortieren, beispielsweise nach dem Namen?

              gruß,
              wahsaga

              --
              /voodoo.css:
              #GeorgeWBush { position:absolute; bottom:-6ft; }
              1. Hello,

                Wenn ich jetzt also

                $data['name'] = array('Hans', 'Olaf', 'Adam');
                $data['alter'] = array(32, 47, 21);

                habe - wie soll ich das mit einer vorhandenen PHP-Array-Funktion sortieren, beispielsweise nach dem Namen?

                Sowas würdest DU ja gar nicht haben, denn erstens würdest Du meinen Vorschlag genau lesen und zweitens wüsstest Du doch selber, dass die Indexe natürlich vergeben werden sollten.

                In obigem Fall würde das zwar auch funktionieren, aber das wäre mir zu unsicher.

                $_data['name'] = array (1=>'Hans', 5=>'Olaf', 22=>'Adam');
                 $_data['alter'] = array(1=>32,     5=>47,     22=>21);

                Die IDs (hier Indexe) muss man natürlich harmonisieren.
                Bei Neubelegung geht es natürlich auch so, wie Du das gemacht hast, wenn die Anzahl und Reihenfolge der Elemente stimmt.

                I.d.R. sind die Daten an IDs gebunden, und dann kann man die auch problemlos als Index für das Array verwenden.

                Die Ausgabefunktion wäre dann:

                #--- Sortierung nach Name durchführen

                $leitspalte = 'name';         ## nur als Beispiel
                  natsort($_data[$leitspalte]);

                #--- nach einer Spalte sortiert ausgeben

                foreach($_data[$leitspalte] as $key => $val)   ## hierzu MUSS das Array vollständig sein [1]!
                  {
                    foreach($_data as $colname => $fieldval)
                    {
                      echo $_data[$colname][$key];
                    }
                    echo "<br>\n";
                  }

                Vereinfacht dargestellt.

                [1] unter vollständig wird hier verstanden, dass zu jeder Spalte und jedem Key auch ein Element vorhanden ist, nötigenfalls eben mit NULL belegt. Sosnt musst Du eben noch ein isset() spendieren.

                Die Funktion ist _universell_.
                Man muss nur die Sortierspalte angeben und die Ausgabe der Datensätze findet in der Soretierung der Spalte statt. Zusammengehörige Daten eines Satzes werden zeilenweise ausgegeben, so wie es üblich ist.

                Was hier nicht geht, ist nach name UND alter zu sortieren.

                Harzliche Grüße vom Berg
                http://www.annerschbarrich.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau

    2. Hello,

      Hi Tom

      Muss das Array so aussehen, oder könnte es auch

      $array['name'][0]   = 'Hans';
      $array['name'][1]   = 'Peter';
      $array['street'][0] = 'Beliebigestraße';
      $array['street'][1] = 'Beispielstraße';

      so herum aufgebaut werden?

      vielen dank für Deinen Vorschlag. Leider muss das Array so aufgebaut sein. Die Daten kommen von einer CSV-API aus einem CRM und üssen da anschließend wieder hin. Den Aufbau zu ändern wäre zu aufwendig.

      Du hast nämlich eine reine Spaltenstruktur und die kann man auch in obiger Form abbilden.
      Das macht zwar eigene Funktionen zum Einfügen und Löschen von Elementen notwendig, die sind aber "Peanuts" gegenüber dem Sortieraufwand, den Du Dir sparst...

      Das vorliegende "Array" kannst Du nämlich gleichzeitig nach _jeder_ Spalte sortiert vorhalten.
      Das ist enorm praktisch.

      Viele Grüße und Danke!

      Maresa

  2. Huhu Maresa,

    b) Hilf mir hier evtl die Funktion array_multisort() weiter

    Ja.

    c) Wie kann ich das realisieren? Könnt Ihr mir helfen?

    So ungefähr müsste es klappen

    $orderby = array();
    foreach ($array as $row){
     $orderby[] = $row['name'];
    }
    array_multisort($orderby, SORT_ASC, $array);

    Schau Dir die Benutzer Kommentare unter php.net an, da findet man eigentlich immer nützliche Tipps.

    Viele Grüße

    lulu

    --
    bythewaythewebsuxgoofflineandenjoytheday
    1. Huhu Maresa,

      Hi lulu

      So ungefähr müsste es klappen

      $orderby = array();
      foreach ($array as $row){
      $orderby[] = $row['name'];
      }
      array_multisort($orderby, SORT_ASC, $array);

      herzlichen Dank für Deine Hilfe. So klappt es!

      Ich das ganze noch ein wenig modifiziert, damit case insensitive sortiert wird:

      $orderby = array();
      foreach ($array as $row){
       $orderby[] = $row['name'];
      }
      $orderby = array_map('strtolower', $orderby);
      array_multisort($orderby, SORT_ASC, SORT_STRING, $array);

      Herzliche Grüße und einen schönen Abend

      Maresa