Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Array - Richtige Sortierung nach mehr Kriterien

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Array - Richtige Sortierung nach mehr Kriterien

    Hallo!

    Ich habe einen Array mit folgenden Inhalt:

    Code:
    Nickname  Punkte 
    Karli      13 
    Hans        9 
    Franzi      7 
    Seppi       5 
    Alois       5
    Hiasi       4
    etc...

    Ich möchte diesen gerne wie folgt sortieren

    Punkte absteigend (wie oben) und wenn zwei gleiche Punkte haben dann nach dem Namen alphabetisch Gross und Kleinschreibung gemischt.

    Ich habe mir die Beispiele mit multisort angesehen aber das funktionier alles irgendwie nicht, vermutich check ich es einfach nicht.

    Danke!
    The string "()()" is not palindrom but the String "())(" is.

    Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
    PHP.de Wissenssammlung | Kein Support per PN

  • #2
    Mittels [MAN]usort[/MAN] kannst du dir eine callback-Funktion schreiben und die Sortierung so vornehmen wie du möchtest.

    Der Aufruf wäre wie folgt:

    PHP-Code:
    function mysort($a$b) {
        
    /* Hier kommt deine Sortierlogik hinein */
    }

    $status usort($array'mysort'); 
    [I]Es ist schon alles gesagt! Nur noch nicht von allen! (Karl Valentin)[/I]
    [I]Wenn du eine weise Antwort verlangst, musst du vernünftig fragen. (Johann Wolfgang von Goethe)[/I]

    Kommentar


    • #3
      Hi!

      Danke das hört sich eigenltich gut an, aber leider versteh ich den Teil mit der Sortierungslogik nicht... im handbuch steht zB

      Wie hat dieser Vergleich was mit der Reihenfolge zu tun? Bzw. wie gebe ich dem Ding "meine" gewünschte Logik mit..

      // Vergleichsfunktion
      function cmp($a, $b) {
      if ($a == $b) {
      return 0;
      }
      return ($a < $b) ? -1 : 1;
      }

      Gibt es da ev. etwas ausführlicheres?

      Juergen
      The string "()()" is not palindrom but the String "())(" is.

      Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
      PHP.de Wissenssammlung | Kein Support per PN

      Kommentar


      • #4
        Deine Vergleichsfunktion bekommt zwei zu vergleichende Elemente $a und $b übergeben. Diese wären in deinem Fall zwei Arrays. Und zwar mit den Einträgen "punkte" und "nickname". Du vergleichst zunächst also die Punkte miteinander ist $a['punkte'] größer als $b['punkte'] muss deine Funktion -1 zurückgeben, da du ja absteigend sortieren möchtest.

        Aus dem Manual bei [MAN]strcmp[/MAN]
        Ist str1 kleiner als str2 wird ein Wert < 0 zurückgegeben, ist str1 größer als str2 ein Wert > 0, und bei Gleichheit gibt die Funktion 0 zurück.
        Genauso soll sich auch deine callback-Funktion verhalten.
        [I]Es ist schon alles gesagt! Nur noch nicht von allen! (Karl Valentin)[/I]
        [I]Wenn du eine weise Antwort verlangst, musst du vernünftig fragen. (Johann Wolfgang von Goethe)[/I]

        Kommentar


        • #5
          Hallo,

          ich bin gerade an dem gleichen Thema, vielleicht erklärt es sich einfacher, wenn man noch nicht so fit ist. Ich versuchs mal und hoffe, dass ich (nett) berichtigt werden, wenn ich quatsch erzähle :

          Also:
          - usort ruft die Sortierungsfunktion (häufig 'cmp-function' für Vergleichsfunktion genannt) auf. Die Funktion kann natürlich auch jeden anderen Namen erhalten.
          - anders als der mit bislang bekannte Funktionsaufruf werden für den Aufruf der Funktion keine Parameter mitgegeben, gleichwohl bekommt die Funktion diese, häufig $a und $b genannt. Frage: Woher kommen die Werte für die Variablen?
          - Diese nimmt sich die Funktion aus dem mitgeschickten array (erstes Argument der Funktion usort). Jeweils zwei der Werte des Arrays werden in $a und $b gepackt und dann verglichen.
          Gibt die Sortierungsfunktion eine 1 zurück, dann bedeutet dies, dass $a größer ist als $b. Gibt sie eine -1 zurück, ist $a kleiner als $b. Wenn beide gleich sind, sollte 0 zurückgegeben werden. Dies führt häufig zu Konstruktionen wie:
          PHP-Code:
           if ($a == $b) return 0;    // wenn gleich dann 0
          return ($a $b) ? : -1// wenn $a größer dann 1, wenn $a kleiner dann -1 
          - Und bei mehrdimensionalen Arrays? Die Frage ist ja dann, nach welchem Wert denn sortiert werden soll. Das Feld des Arrays, nach dem sortiert werden soll, muss dann angegeben werden. Also nicht mehr einfach
          PHP-Code:
           if ($a == $b) ... 
          sondern, wenn z.B. nach dem Vornamen sortiert werden soll
          PHP-Code:
           if ($a['vorname'] == $b['vorname']) ... 
          - Was einem jetzt die Möglichkeit gibt, auch nach zwei Kriterien zu sortieren, indem man z.B. bei Gleichheit nicht sofort mit der Sortierung aufhört
          PHP-Code:
           if ($a['vorname'] == $b['vorname']) return 
          sondern weitersortiert
          PHP-Code:
          if ($a['vorname'] == $b['vorname']) {
            if (
          $a['name'] == $b['name'] return 0;
            return 
          $a['name'] > $b['name'] ? : -1;

          Bis hierhin habe ich etwas gebraucht, aber ich hoffe dass richtig verstanden zu haben, denn wenn ja, ist das ziemlich cool und macht array_multisort echt überflüssig - naja, vielleicht fast, in Spezialfällen mag das immer noch einfacher sein.

          Gruß
          Peter

          Kommentar


          • #6
            array_multisort() ist hier genau das mittel der Wahl.

            Vorallem gibt es im Handbuch exakt ein Beispiel welches dem hiuer genanntem Problem fast wie ein Ei dem anderem gleicht und nahezu mit copy&paste kopiert werden kann.

            Das funktioniert folgendermaßen:

            Die Funktion erwartet als ersten Parameter ein Array mit den Werten anch denen sortiert werden soll, als zweiten die Sortierrichtung.

            Von diesen Paaren können beliebig viele nacheinander angegeben werden.

            Als letzten Parameter kann dnan noch das Array mitgegeben werden welches die gemeinsamen Schlüssel der einzelnen Arrays enthält um den Bezug zwischen den Zeilen der Spalten wiederherstellen zu können.

            PHP-Code:
            <?php
            $data
            [] = array('Band' => 67'Auflage' => 2);
            $data[] = array('Band' => 86'Auflage' => 1);
            $data[] = array('Band' => 85'Auflage' => 6);
            ?>
            Das Ausgangsarray. Diese Struktur wird wohl auch das Array des Themenerstellers haben.

            Nun werden die Daten aber als Spalten gebraucht und nicht als Zeilen:

            PHP-Code:
            <?php
            $band 
            = array(=> 67,
                          
            => 86,
                          
            => 85);

            $auflage = array(=> 2,
                             
            => 1,
                             
            => 6);
            ?>
            durch den letzten Parameter $data von array_multisort wird durch die Schlüssel im Ausgangsarray ein Bezug zwischen $band und $auflage hergestellt.

            Der Rest sollte sich ergeben bzw. kann per c&p aus dem Handbuch übernommen werden.
            "Alles im Universum funktioniert, wenn du nur weißt wie du es anwenden musst".

            Kommentar


            • #7
              Ich denke am einfachsten kann man sich das ganze mit den Callbacks anhand von einem Haufen gemischelter Karten vorstellen, die es zu sortieren gilt.

              Man stelle sich zwei Akteure vor:
              Akteur 1 kann anhand von zwei Karten sagen, welche höherwertig ist bzw. ob sie gleichwertig sind (legt die Sortierreihenfolge fest)
              Akteur 2 nimmt diesen Dienst in Anspruch und kann damit den gesamten Haufen sortieren. Je cleverer er das macht, desto schneller ist er fertig (Effizienz des Sortieralgorithmus)

              Um Akteur 2 kümmert sich PHP (ich nehme mal an es wird Quicksort verwendet) und stellt eine Schnittstelle mit usort() zur Verfügung. Akteur 1 kann selbst geschrieben werden, hier kommen $a ($karte_x) und $b ($karte_y) eben ins Spiel. Beim Kartenhaufen könnte diese Funktion jetzt also festlegen, ob 10 hoch gespielt wird oder nicht.

              Und egal ob dieser Array jetzt multidimensional ist oder nicht, der Funktion werden eben die Elemente des zu sortierenden Arrays übergeben, ob es sich nun um einen Array handelt oder nicht. Das macht es eigentlich recht intuitiv.

              Dafür sind native Funktionen wie array_multisort() eben häufig auch deutlich schneller.
              "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

              Kommentar


              • #8
                Also das mit der callback Geschichte werd ich mir auf jeden Fall nochmals genauer anschauen, rein schon weil ich neugirig drauf bin

                PHP-Code:
                <?php
                $data
                [] = array('Band' => 67'Auflage' => 2);
                $data[] = array('Band' => 86'Auflage' => 1);
                $data[] = array('Band' => 85'Auflage' => 6);
                ?>
                Das Ausgangsarray. Diese Struktur wird wohl auch das Array des Themenerstellers haben.
                Mein Array hat nur ein Feld key => wert fertig..
                Code:
                Nickname => Punkte 
                Karli    => 13 
                Hans     =>  9 
                Franzi   =>  7 
                Seppi    =>  5 
                Alois    =>  5
                Hiasi    =>  4
                und ich muss sortieren im SQL wäre es so: ORDER BY Punkte (=wert) DESC, Nickname (=key) ASC

                Hab es derzeit mal so gelöst funktioniert bisher mal..
                PHP-Code:
                function arraySpecialSort($gesamtRanking) {
                    
                # sortiert so wie ORDER BY Punkte DESC, Nickname
                    
                foreach($gesamtRanking as $user => $punkte) {
                        
                $tmp_array[$punkte][] = $user;
                    }
                    
                krsort($tmp_arraySORT_NUMERIC);
                    
                #dump($tmp_array);
                    
                    
                unset($gesamtRanking);  
                    foreach(
                $tmp_array as $punkte => $array) {
                        if(
                count($array) > 1) {
                            
                sort($array);
                            foreach(
                $array as $user)
                                
                $gesamtRanking[$user] = $punkte;
                        } else {
                            
                $gesamtRanking[$array[0]] = $punkte;
                        }
                    }
                    return 
                $gesamtRanking;

                Juergen
                The string "()()" is not palindrom but the String "())(" is.

                Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                PHP.de Wissenssammlung | Kein Support per PN

                Kommentar


                • #9
                  Wo kommen die Werte her? Eine Datenbank kann auch sortieren ...
                  "[URL="http://www.youtube.com/watch?v=yMAa_t9k2VA&feature=youtu.be&t=25s"]Mein Name ist Lohse, ich kaufe hier ein.[/URL]"

                  Kommentar


                  • #10
                    Macht die auch...

                    Es gibt ganz vereinfacht Spiele in der DB und es gibt Tipps in der DB.. Bei der Auswertung hier wird...

                    1. Erstmal alle Tipps mit dem entsprechenden Usern und den Spiel-Daten DB geholt...
                    Code:
                    $sql="SELECT
                             u.Nickname,
                             s.SpielID, DATE_FORMAT(s.Beginn,'%d.%m.%Y %H:%i') AS Beginn, s.ErgebnisTor1, s.ErgebnisTor2,
                             t.TippTor1, t.TippTor2
                          FROM (tabspiele s, tabuser u)
                          LEFT JOIN tabtipps t
                             ON t.Nickname = u.Nickname
                             AND t.SpielIDRef = s.SpielID
                          WHERE s.Beginn < DATE_ADD(now(), INTERVAL +2 MINUTE) 
                          ORDER BY u.Nickname";
                    2. dann wird der sql-fetch durchlaufen und mit hinterlegter Logik (vergleiche Spielergebnis mit Tipp und entsprechende Punktevergabe) daraus Punkte zu jedem Spiel berechnet und die direkt in den Array geschreiben

                    PHP-Code:
                        $gesamtRanking = array();
                        while (
                    $data=mysql_fetch_array($result)) {
                           
                               
                    # Berechnung Punkte
                            
                    $nickname $data['Nickname'];
                            
                    $punkteJeSpiel calcPunkteJeSpiel($data['ErgebnisTor1'], $data['ErgebnisTor2'], $data['TippTor1'], $data['TippTor2']);
                            
                            
                    # array füllen $gesamtRanking[$nickname] => punkte
                            
                    if(isset($gesamtRanking[$nickname])) {
                                
                    $gesamtRanking[$nickname] += $punkteJeSpiel;
                            } else {
                                
                    $gesamtRanking[$nickname] = $punkteJeSpiel;
                            }
                        } 
                    3. Der Array noch sortiert...

                    Vermutlich wäre es irgendwie möglich die Punkteberechnungslogik auch in SQL zu machen aber da bald noch Zusatzpunkte möglich sind die eigene Tabellen etc.. haben, habe ich das gelassen, ich bin froh das es so soweit funkt

                    Juergen
                    The string "()()" is not palindrom but the String "())(" is.

                    Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                    PHP.de Wissenssammlung | Kein Support per PN

                    Kommentar


                    • #11
                      Zitat von hausl Beitrag anzeigen
                      Mein Array hat nur ein Feld key => wert fertig..
                      Code:
                      Nickname => Punkte 
                      Karli    => 13 
                      Hans     =>  9 
                      Franzi   =>  7 
                      Seppi    =>  5 
                      Alois    =>  5
                      Hiasi    =>  4
                      Und das ist in Stein gemeiselt? Fest und unumkehrbar in keinster Art und Weise?

                      PHP-Code:
                      $nicknames = array();
                      $points = array();
                      $sortArray = array();

                      foreach(
                      $dasArray AS $key => $value) {
                          
                      $nicknames[] = $key;
                          
                      $points[] = $value;
                          
                      $sortArray[] = array('nickname' => $key'points' => $value);
                      }

                      array_multisort($pointsSORT_DESC$nicknamesSORT_ASC$sortArray); 
                      Sollte es eigentlich tun... ich bin mir grad nicht sicher ob das mit den Schlüsseln alles so passt aber müsste wenn ich nicht einen gewaltigen Logikfehler hab, ist shcon spät.
                      "Alles im Universum funktioniert, wenn du nur weißt wie du es anwenden musst".

                      Kommentar


                      • #12
                        [OT]
                        Zitat von Dark Guardian Beitrag anzeigen
                        Und das ist in Stein gemeiselt?
                        Falls ja, haben sich da bestimmt einige Meisen den Schnabel dran gebrochen ...
                        [/OT]
                        [SIZE="1"]RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?[/SIZE]

                        Kommentar


                        • #13
                          Zitat von Dark Guardian Beitrag anzeigen
                          Und das ist in Stein gemeiselt? Fest und unumkehrbar in keinster Art und Weise?
                          Genau! weil da könnt ja jeder kommen (und zwitschern ähm meise(l)n und so, sorry *gg*)

                          Im ernst.. ich probier das morgen gerne und wenn das selbe rauskommt, dann

                          1. merci vielmals!
                          2. wird das eingbaut!

                          Juergen
                          The string "()()" is not palindrom but the String "())(" is.

                          Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                          PHP.de Wissenssammlung | Kein Support per PN

                          Kommentar


                          • #14
                            Also.. (Hirnschmazl erst morgenwieder)

                            wenn ich "meine" funktion durch deine ersetze gehts nicht..

                            PHP-Code:
                            function arraySpecialSort($gesamtRanking) {

                                
                            $nicknames = array(); 
                                
                            $points = array(); 
                                
                            $sortArray = array(); 
                                
                                foreach(
                            $gesamtRanking AS $key => $value) { 
                                    
                            $nicknames[] = $key
                                    
                            $points[] = $value
                                    
                            $sortArray[] = array('nickname' => $key'points' => $value); 
                                } 
                                
                            array_multisort($pointsSORT_DESC$nicknamesSORT_ASC$sortArray);
                                return 
                            $points;
                            }


                            function 
                            arraySpecialSortOLD($gesamtRanking) {
                                
                            # sortiert so wie ORDER BY Punkte DESC, Nickname
                                
                            foreach($gesamtRanking as $user => $punkte) {
                                    
                            $tmp_array[$punkte][] = $user;
                                }
                                
                            krsort($tmp_arraySORT_NUMERIC);
                                
                            #dump($tmp_array);
                                
                                
                            unset($gesamtRanking);  
                                foreach(
                            $tmp_array as $punkte => $array) {
                                    if(
                            count($array) > 1) {
                                        
                            sort($array);
                                        foreach(
                            $array as $user)
                                            
                            $gesamtRanking[$user] = $punkte;
                                    } else {
                                        
                            $gesamtRanking[$array[0]] = $punkte;
                                    }
                                }
                                return 
                            $gesamtRanking;

                            Der Array gibt zu wenig zurück der key müßten die namen alphabetisch sein.

                            PHP-Code:
                            <h2>Angemeldet als Franzi</h2>Array
                            (
                                [
                            0] => 10
                                
                            [1] => 10
                                
                            [2] => 8
                                
                            [3] => 6
                                
                            [4] => 6

                            Gedanken dazu.. morgen dann
                            The string "()()" is not palindrom but the String "())(" is.

                            Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                            PHP.de Wissenssammlung | Kein Support per PN

                            Kommentar


                            • #15
                              Zitat von hausl Beitrag anzeigen
                              Gedanken dazu.. morgen dann
                              Du gibst ja auch ein völlig falsches Array zurück.... das passiert wenn man Code nur kopiert und nicht versteht... außerdem gibt meine Funktion die Nicknamen nicht als Schlüssel zurück...

                              ... und wie gesagt: es ist schon spät, Bier und Anti-Depressiva sind alle, da verwechselt man mal die eine oder andere Form eines s-Lautes... XD
                              "Alles im Universum funktioniert, wenn du nur weißt wie du es anwenden musst".

                              Kommentar

                              Lädt...
                              X