Michael: Array nach mehreren Feldern sortieren

Hallo,

mit dem folgenden kann ich meinen Array "kunde" wunderbar nach Nachname oder  nach jedem anderen Feld sortieren lassen.
Aber wie kann ich erreichen, das nicht nur nach einem Feld sondern nach mehreren Feldern sortiert wird.
Also z.B. zuerst nach "nachname" dann nach "ort" und danach nach "strasse"

$kunde[0] = array("vorname"=>"Hans",  "nachname"=>"Maier",  "strasse"=>"Nussweg 12",  "Ort"=>"München");
 $kunde[1] = array("vorname"=>"Manuela", "nachname"=>"Schmidt",  "strasse"=>"Bahnhofstr. 34","Ort"=>"Frankfurt");
 $kunde[2] = array("vorname"=>"Klaus",  "nachname"=>"Michaelis","strasse"=>"Mühlweg 8",  "Ort"=>"Hamburg");
 $kunde[3] = array("vorname"=>"Sabine",  "nachname"=>"Jabst",  "strasse"=>"Flurweg 8",  "Ort"=>"Dresden");
 $kunde[4] = array("vorname"=>"Gerhard", "nachname"=>"Blum",  "strasse"=>"Wiesenweg 77",  "Ort"=>"Berlin");

Function sortiere_kunde(&$a)
  {
  Function cmp_array_nachname ($a, $b) {return strcmp($a["nachname"], $b["nachname"]);}
  usort($a, "cmp_array_nachname");
  }

sortiere_kunde($kunde);

echo "kunde: ";

echo "<pre>";
  print_r( $kunde );
 echo "</pre>";

Hat jemand einen Tipp für mich?

Vielen Dank im voraus

Gruß Michael

  1. Also z.B. zuerst nach "nachname" dann nach "ort" und danach nach "strasse"

    Ganz einfach. Du sortierst in deinem Fall genau in der Reihenfolge, die du aufgezählt hast. Erst nach Nachname, dann nach Ort und dann nach Strasse. Also drei Sortierungen nacheinandner.

    Im Normalfall hast du dann eine Sortierung nach diesen Kriterien.

    1. Hallo mega,

      danke für deine Antwort!

      Ganz einfach. Du sortierst in deinem Fall genau in der Reihenfolge, die du aufgezählt hast. Erst nach Nachname, dann nach Ort und dann nach Strasse. Also drei Sortierungen nacheinandner

      Du meinst so:

      $kunde[0] = array("vorname"=>"Hans",  "nachname"=>"Maier",  "strasse"=>"Nussweg 12",  "Ort"=>"München");
       $kunde[1] = array("vorname"=>"Manuela", "nachname"=>"Schmidt",  "strasse"=>"Bahnhofstr. 34","Ort"=>"Frankfurt");
       $kunde[2] = array("vorname"=>"Klaus",  "nachname"=>"Michaelis","strasse"=>"Mühlweg 8",  "Ort"=>"Hamburg");
       $kunde[3] = array("vorname"=>"Sabine",  "nachname"=>"Jabst",  "strasse"=>"Flurweg 8",  "Ort"=>"Dresden");
       $kunde[4] = array("vorname"=>"Gerhard", "nachname"=>"Blum",  "strasse"=>"Wiesenweg 77",  "Ort"=>"Berlin");

      Function sortiere_kunde(&$a)
        {
        Function cmp_array_nachname ($a, $b) {return strcmp($a["nachname"], $b["nachname"]);}
        Function cmp_array_ort   ($a, $b) {return strcmp($a["ort"], $b["ort"]);}
        usort($a, "cmp_array_nachname");
        usort($a, "cmp_array_ort");
        }

      sortiere_kunde($kunde);

      echo "kunde: ";

      echo "<pre>";
        print_r( $kunde );
       echo "</pre>";

      Im Normalfall hast du dann eine Sortierung nach diesen Kriterien.

      Da wird aber die Sortierung nach "nachname" durch die Sortierung nach "ort" wieder zerstört. Oder habe ich etwas falsch verstanden?

      1. echo $begrüßung;

        Ganz einfach. Du sortierst in deinem Fall genau in der Reihenfolge, die du aufgezählt hast. Erst nach Nachname, dann nach Ort und dann nach Strasse. Also drei Sortierungen nacheinandner
        Da wird aber die Sortierung nach "nachname" durch die Sortierung nach "ort" wieder zerstört. Oder habe ich etwas falsch verstanden?

        Nicht drei Sortierungen sondern bis zu drei Vergleiche möchtest du haben. Wenn beim ersten Vergleich nach dem Nachnamen Gleichheit ermittelt wird, musst du weiter die Orte vergleichen. Bei Ungleichheit hast du ein Ergebnis, bei Gleichheit geht es mit der Straße weiter.

        echo "$verabschiedung $name";

        1. Hallo,

          Nicht drei Sortierungen sondern bis zu drei Vergleiche möchtest du haben. Wenn beim ersten Vergleich nach dem Nachnamen Gleichheit ermittelt wird, musst du weiter die Orte vergleichen. Bei Ungleichheit hast du ein Ergebnis, bei Gleichheit geht es mit der Straße weiter.

          Das wird also etwas komplexer.

          Eigentlich ist das doch eine Thematik die ständig gebraucht wird. Gibt es dafür keine fertige PHP Funktion oder eine Klasse?

          Muss ja nicht unbedingt das Rad zum 1000x neu erfinden.

          Gruß Michael

          1. Hallo,

            Das Problem ist mit PHP lösbar, aber so wie Du Dein Problem schilderst, wäre vielleicht der Einsatz einer Datenbank sinnvoll.

            Vermutlich wirst Du nicht nur Kundendaten sondern auch deren Bestellungen/Status und Rechnungen/Status speichern wollen? Möglicherweise auch noch weitere Informationen.
            Datenbanken sind im Sortieren jedenfalls echt gut (ORDER BY). Wenn Du so etwas wie einen Webshop programmieren möchtest, solltest Du vielleicht einen Datenbankeinsatz in Erwägung ziehen.

            netten Tag
            ^da Powl

            --
            ===============================
            powl.hat-gar-keine-homepage.de/
            1. Hallo,

              Das Problem ist mit PHP lösbar,

              Wie???

              aber so wie Du Dein Problem schilderst, wäre vielleicht der Einsatz einer Datenbank sinnvoll.

              Es muss in php gemacht werden. In MySQL wäre das überhaupt kein Problem ich weiß. Es geht aber nicht anders.

              Gruß Michael

              1. echo $begrüßung;

                Das Problem ist mit PHP lösbar,
                Wie???

                Ich hab doch den Lösungsweg schon beschrieben. Wo genau hast du da ein Verständnisproblem?

                Einen Vergleich mit strcmp() hast du ja schon in deiner benutzerdefinierten Vergleichsfunktion verwendet. Du darfst nun nur nicht das Ergebnis sofort zurückgeben sondern musst im Falle von Gleichheit mit dem nächsten Vergleich weitermachen.

                echo "$verabschiedung $name";

                1. Hallo dedlfix,

                  danke für Deine Antworten!

                  Einen Vergleich mit strcmp() hast du ja schon in deiner benutzerdefinierten Vergleichsfunktion verwendet. Du darfst nun nur nicht das Ergebnis sofort zurückgeben sondern musst im Falle von Gleichheit mit dem nächsten Vergleich weitermachen.

                  Ich hatte mir gedacht so sollte es gehen, tut es aber leider nicht:

                  $kunde[0] = array("vorname"=>"Hans",  "nachname"=>"Michaelis","strasse"=>"Nussweg 12",  "ort"=>"Hamburg");
                   $kunde[1] = array("vorname"=>"Manuela", "nachname"=>"Michaelis","strasse"=>"Bahnhofstr. 34","ort"=>"Berlin");
                   $kunde[2] = array("vorname"=>"Klaus",  "nachname"=>"Michaelis","strasse"=>"Mühlweg 8",  "ort"=>"Hamburg");
                   $kunde[3] = array("vorname"=>"Sabine",  "nachname"=>"Jabst",  "strasse"=>"Flurweg 8",  "ort"=>"Dresden");
                   $kunde[4] = array("vorname"=>"Gerhard", "nachname"=>"Blum",  "strasse"=>"Wiesenweg 77",  "ort"=>"Berlin");
                   $kunde[5] = array("vorname"=>"Marion",  "nachname"=>"Michaelis","strasse"=>"Ahornweg 12",  "ort"=>"Hamburg");

                  Function sortiere_kunde(&$a)
                    {
                    Function cmp_array_strasse ($a, $b)
                     {
                     return(strcmp($a["strasse"], $b["strasse"]));
                     }

                  Function cmp_array_ort ($a, $b)
                     {
                     $x=0; $x=strcmp($a["ort"], $b["ort"]);
                     if ($x==0)
                      {
                      $sort_strasse=array();
                      $sort_strasse[0]=$a;
                      $sort_strasse[1]=$b;
                      usort($sort_strasse, "cmp_array_strasse");
                      }
                     else return $x;
                     }

                  Function cmp_array_nachname ($a, $b)
                     {
                     $x=0; $x=strcmp($a["nachname"], $b["nachname"]);
                     if ($x==0)
                      {
                      $sort_nachname=array();
                      $sort_nachname[0]=$a;
                      $sort_nachname[1]=$b;
                      usort($sort_nachname, "cmp_array_ort");
                      }
                     else return $x;
                     }
                    usort($a, "cmp_array_nachname");
                    }

                  sortiere_kunde($kunde);

                  echo "kunde: ";

                  echo "<pre>";
                    print_r( $kunde );
                   echo "</pre>";

                  Die Ausgabe sieht so aus:

                  (
                      [0] => Array
                          (
                              [vorname] => Gerhard
                              [nachname] => Blum
                              [strasse] => Wiesenweg 77
                              [ort] => Berlin
                          )

                  [1] => Array
                          (
                              [vorname] => Sabine
                              [nachname] => Jabst
                              [strasse] => Flurweg 8
                              [ort] => Dresden
                          )

                  [2] => Array
                          (
                              [vorname] => Marion
                              [nachname] => Michaelis
                              [strasse] => Ahornweg 12
                              [ort] => Hamburg
                          )

                  [3] => Array
                          (
                              [vorname] => Klaus
                              [nachname] => Michaelis
                              [strasse] => Mühlweg 8
                              [ort] => Hamburg
                          )

                  [4] => Array
                          (
                              [vorname] => Manuela
                              [nachname] => Michaelis
                              [strasse] => Bahnhofstr. 34
                              [ort] => Berlin
                          )

                  [5] => Array
                          (
                              [vorname] => Hans
                              [nachname] => Michaelis
                              [strasse] => Nussweg 12
                              [ort] => Hamburg
                          )

                  )

                  Stimmt nicht so ganz. Wo liegt da noch der Fehler? Danke.

                  Grüße

                  Was ist daran falsch?

                  1. echo $begrüßung;

                    Einen Vergleich mit strcmp() hast du ja schon in deiner benutzerdefinierten Vergleichsfunktion verwendet. Du darfst nun nur nicht das Ergebnis sofort zurückgeben sondern musst im Falle von Gleichheit mit dem nächsten Vergleich weitermachen.
                    Ich hatte mir gedacht so sollte es gehen, tut es aber leider nicht:

                    Du denkst anscheinend viel zu umständlich. Deine Vergleichsfunktion bekommt zwei der Datensätze übergeben. Wenn bei beiden das erste Kriterium übereinstimmt, reicht es, mit einem weiteren strcmp() das zweite Kriterium zu vergleichen. Du musst dazu weder ein neues Array anlegen, noch eine eigene Vergleichsfunktion schreiben, und dieses Array auch nicht sortieren lassen, wobei du das Ergebnis dessen ignorierst.

                    Das ist in mehr oder weniger Pseudocode das was du suchst

                    wenn 0 == $ergebnis = strcmp($a['x'], $b['x'])
                        wenn 0 == $ergebnis = strcmp($a['y'], $b['y'])
                          return strcmp($a['z'], $b['z']);
                        else
                          return $ergebnis;
                      else
                        return $ergebnis;

                    Oder etwas abgekürzt:

                    wenn 0 == $ergebnis = strcmp($a['x'], $b['x'])
                        wenn 0 == $ergebnis = strcmp($a['y'], $b['y'])
                          return strcmp($a['z'], $b['z']);
                      return $ergebnis;

                    Allgemeine Anmerkungen:

                    Function sortiere_kunde(&$a)
                      {
                      Function cmp_array_strasse ($a, $b)

                    Das Schachteln von Funktionsdefinitionen bringt bei mehrfachem Aufruf der äußeren Funktion außer Ärger keine Vorteile. Eine Funktion wird immer global angelegt.

                    $x=0; $x=strcmp($a["ort"], $b["ort"]);

                    Sicher ist sicher? Die Zuweisung des Ergebnisses von strcmp() zu $x findet in jedem Fall statt. Die vorherige Zuweisung $x=0; wird damit ungenutzt überschrieben.

                    Was ist daran falsch?

                    Die tatsächliche Funktionsweise (auch selbst geschriebenen) Codes versteht man meist dadurch besser, dass man Kontrollausgaben einbaut und so das Verhalten der Variablen und die Ergebnisse von Ausdrücken überwacht.

                    echo "$verabschiedung $name";

                    1. Hallo und vielen Dank an dedlfix!

                      Das ist in mehr oder weniger Pseudocode das was du suchst

                      wenn 0 == $ergebnis = strcmp($a['x'], $b['x'])
                          wenn 0 == $ergebnis = strcmp($a['y'], $b['y'])
                            return strcmp($a['z'], $b['z']);
                          else
                            return $ergebnis;
                        else
                          return $ergebnis;

                      Oder etwas abgekürzt:

                      wenn 0 == $ergebnis = strcmp($a['x'], $b['x'])
                          wenn 0 == $ergebnis = strcmp($a['y'], $b['y'])
                            return strcmp($a['z'], $b['z']);
                        return $ergebnis;

                      Dieser Anstoß hat genügt, den Rest habe ich ebenfalls dankend zur Kenntnis genommen.

                      Hier nun die fertige Lösung (vielleicht kann es jemand gebrauchen und hat es dann damit etwas leichter und schneller als ich)
                      Im folgenden Beispiel werden die Adressen nach "nachname", "ort" und "strasse" sortiert.

                      $kunde = array(
                      "0" => array("vorname"=>"Hans",  "nachname"=>"Michaelis", "strasse"=>"Nussweg 12",  "ort"=>"Hamburg"),
                      "1" => array("vorname"=>"Manuela",  "nachname"=>"Michaelis", "strasse"=>"Bahnhofstr. 34", "ort"=>"Berlin"),
                      "2" => array("vorname"=>"Klaus",  "nachname"=>"Michaelis", "strasse"=>"Mühlweg 8",  "ort"=>"Hamburg"),
                      "3" => array("vorname"=>"Sabine",  "nachname"=>"Jabst",   "strasse"=>"Flurweg 8",   "ort"=>"Dresden"),
                      "4" => array("vorname"=>"Gerhard",  "nachname"=>"Blum",   "strasse"=>"Wiesenweg 77",  "ort"=>"Berlin"),
                      "5" => array("vorname"=>"Marion",  "nachname"=>"Michaelis", "strasse"=>"Ahornweg 12",  "ort"=>"Hamburg")
                      );

                      echo "<pre>";
                      print_r($kunde);
                      echo "</pre>";

                      Function cmp_adresse($a, $b )
                       {
                       if (0 == $x = strcmp($a['nachname'], $b['nachname']))
                        {
                        if (0 == $x = strcmp($a['ort'], $b['ort']))
                         {return strcmp($a['strasse'], $b['strasse']);}
                        }
                       return $x;
                       }

                      usort($kunde, 'cmp_adresse') ;

                      echo "<pre>";
                       print_r( $kunde );
                      echo "</pre>";

                      Für Verbesserungs- und / oder Optimierungsvorschläge bin ich jederzeit offen.

                      Danke für die Unterstützung

                      Grüße Michael