Mike: array_unique sortiert nicht richtig und macht Fehler?

Hallo,

bin mir zwar nicht sicher ob das Folgende nicht vielleicht doch so OK ist, zumindest würde ich aber eine andere Ausgabe von array_unique() erwarten.

Script
  
<?php  
  
$ar = array('rot','gelb','grün','rot','234fw343','blau','gold');  
  
$ar1 = array_unique($ar);  
$ar2 = array_unique($ar,SORT_REGULAR);  
$ar3 = array_unique($ar,SORT_NUMERIC);  
$ar4 = array_unique($ar,SORT_STRING);  
$ar5 = array_unique($ar,SORT_LOCALE_STRING);  
  
  
  
print_r($ar1);  
print_r($ar2);  
print_r($ar3);  
print_r($ar4);  
print_r($ar5);  
  
?>  

Bei der Ausgabe ändert sich, egal mit welchen sort_flags, nichts. Außer SORT_NUMERIC, wobei dann einfach Werte wegfallen. Ziel war es eine alphabetische Sortierung zu erhalten, klar geht das auch mit anderen Möglichkeiten, doch hatte ich das so im Manual verstanden, dass es mit den Flags auch funktionieren müsste? Aber dass bei numerischer Sortierung einfach Werte wegfallen, dürfte doch auch nicht richtig sein?

Ausgabe
  
Array  
(  
    [0] => rot  
    [1] => gelb  
    [2] => grün  
    [4] => 234fw343  
    [5] => blau  
    [6] => gold  
)  
Array  
(  
    [0] => rot  
    [1] => gelb  
    [2] => grün  
    [4] => 234fw343  
    [5] => blau  
    [6] => gold  
)  
Array  
(  
    [0] => rot  
    [4] => 234fw343  
)  
Array  
(  
    [0] => rot  
    [1] => gelb  
    [2] => grün  
    [4] => 234fw343  
    [5] => blau  
    [6] => gold  
)  
Array  
(  
    [0] => rot  
    [1] => gelb  
    [2] => grün  
    [4] => 234fw343  
    [5] => blau  
    [6] => gold  
)  
  
  

Gruss
Mike

  1. Lieber Mike,

    ich hatte array_unique bisher nur als Filter, nicht jedoch als Sortierer in Erinnerung. Dass dieses Flag ab 5.2.9 hinzugefügt wurde, hatte ich bisher nicht wahrgenommen.

    Was spricht denn dagegen, nach dem Filtern eine übliche Sortierung mit den ebenso üblichen Verdächtigen (sort, usort, uasort, asort, etc.) vorzunehmen? Die Lesbarkeit des Codes wird sicherlich nicht darunter leiden und das Ergebnis besser steuerbar!

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Hallo Felix,

      ich hatte array_unique bisher nur als Filter, nicht jedoch als Sortierer in Erinnerung. Dass dieses Flag ab 5.2.9 hinzugefügt wurde, hatte ich bisher nicht wahrgenommen.

      na ja, es war auch vorher schon eine Sortierfunktion enthalten, nur nicht steuerbar:
      "....Vor 5.2.9 wurde die Sortierung intern mit SORT_STRING durchgeführt...."

      Was spricht denn dagegen, nach dem Filtern eine übliche Sortierung mit den ebenso üblichen Verdächtigen (sort, usort, uasort, asort, etc.) vorzunehmen? Die Lesbarkeit des Codes wird sicherlich nicht darunter leiden und das Ergebnis besser steuerbar!

      Ich hatte schon geschrieben, dass es natürlich andere Möglichkeiten gibt, die mich aber nicht interessieren. Mich interessiert allein, ob die Funktion so arbeitet wie sie es soll oder doch ein BUG vorliegt.

      Gruss
      Mike

  2. Hi,

    $ar = array('rot','gelb','grün','rot','234fw343','blau','gold');

    $ar1 = array_unique($ar);
    $ar2 = array_unique($ar,SORT_REGULAR);
    $ar3 = array_unique($ar,SORT_NUMERIC);
    $ar4 = array_unique($ar,SORT_STRING);
    $ar5 = array_unique($ar,SORT_LOCALE_STRING);

      
    
    > Aber dass bei numerischer Sortierung einfach Werte wegfallen, dürfte doch auch nicht richtig sein?  
      
    doch, ich verstehe das so, dass das Array zunächst anhand der numerischen Werte seiner Feldinhalte sortiert und dann auf eindeutige Werte (unique) reduziert wird. Der Sortierschritt ergäbe theoretisch folgenden Zwischenstand:  
      
    
    > Array  
    > (  
    >     [0] => rot  
    >     [1] => gelb  
    >     [2] => grün  
    >     [3] => rot  
    >     [5] => blau  
    >     [6] => gold  
    >     [4] => 234fw343  
    > )  
      
    Warum das? Weil alle Werte, die nicht mit einer Ziffer beginnen, numerisch als 0 interpretiert werden. Und wenn jetzt als zweiter Schritt die Eliminierung der mehrfach auftretenden Werte durchläuft, fallen "gelb", "grün", das zweite "rot", "blau" und "gold" raus, weil sie alle 0 ergeben, der Wert 0 aber durch den ersten "rot"-Eintrag schon da ist.  
      
    So long,  
     Martin  
      
      
    PS: Wieso markierst du deine PHP-Debugausgaben hier als HTML?
    
    -- 
    Keine Sorge, wir finden für jede Lösung ein Problem.  
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    
    1. Hallo,

      Aber dass bei numerischer Sortierung einfach Werte wegfallen, dürfte doch auch nicht richtig sein?

      doch, ich verstehe das so, dass das Array zunächst anhand der numerischen Werte seiner Feldinhalte sortiert und dann auf eindeutige Werte (unique) reduziert wird. Der Sortierschritt ergäbe theoretisch folgenden Zwischenstand:

      Array
      (
          [0] => rot
          [1] => gelb
          [2] => grün
          [3] => rot
          [5] => blau
          [6] => gold
          [4] => 234fw343
      )

      Warum das? Weil alle Werte, die nicht mit einer Ziffer beginnen, numerisch als 0 interpretiert werden. Und wenn jetzt als zweiter Schritt die Eliminierung der mehrfach auftretenden Werte durchläuft, fallen "gelb", "grün", das zweite "rot", "blau" und "gold" raus, weil sie alle 0 ergeben, der Wert 0 aber durch den ersten "rot"-Eintrag schon da ist.

      ok, etwas verwirrend. Selbst wenn deine Schlussfolgerung richtig ist, ist dieses Verhalten wirklich so gewünscht bei dieser Funktion? Dass hier eben unkalkulierbar Werte wegfallen? Ich hätte es noch verstanden wenn es gar keinen Output gäbe, weil kein Wert numerisch oder nur der 234fw343 Wert weil dieser zumindest mit einer Zahl anfängt. Aber so...

      Nehmen wir mal den normalen Fall an, für den diese Funktion eigentlich konzipiert sein sollte:

      Du hast ein großes Array mit vielen auch gleichen Werten. Die Doppler sollen raus und das Ganze, wie auch immer(alphabetisch, usw...), sortiert werden.

      Was passiert? Sortierung erfolgt nicht, also kein Verlass. Schlimmer noch, sortierst Du numerisch, weil Du denkst da wären nur Zahlen drin, was aber nicht so ist, spuckt die Funktion nur Teile raus. Soll das wirklich so gewollt sein? Zumindest eine der String-Sortierungen sollte doch funktionieren?

      Gruss
      Mike

      PS: Wieso markierst du deine PHP-Debugausgaben hier als HTML?

      Weil es ja nur Browseroutput ist und kein PHP-Code. Aber wenn es hier anders gewünscht ist, mach ich das gerne demnächst als PHP ;-)

      1. Hi,

        Warum das? Weil alle Werte, die nicht mit einer Ziffer beginnen, numerisch als 0 interpretiert werden. Und wenn jetzt als zweiter Schritt die Eliminierung der mehrfach auftretenden Werte durchläuft, fallen "gelb", "grün", das zweite "rot", "blau" und "gold" raus, weil sie alle 0 ergeben, der Wert 0 aber durch den ersten "rot"-Eintrag schon da ist.
        ok, etwas verwirrend. Selbst wenn deine Schlussfolgerung richtig ist, ist dieses Verhalten wirklich so gewünscht bei dieser Funktion?

        das weiß ich nicht. Ehrlich gesagt, ich hätte es auch nicht erwartet. Ich hätte auch gedacht, dass die Uniquification als erster Schritt abläuft, und erst im zweiten Schritt optional(!) die verbliebenen Werte sortiert werden.

        Andererseits: Wer numerisch sortiert, der erwartet numerische Werte. Nicht-numerische Einträge sollten dann also gar nicht vorkomemn bzw. in einer vorgelagerten Eingabeprüfung schon reklamiert worden sein. Wenn diese Einträge dann in der weiteren Verarbeitung unter den Tisch fallen, ist das gar nicht so falsch.

        Nehmen wir mal den normalen Fall an, für den diese Funktion eigentlich konzipiert sein sollte:
        Du hast ein großes Array mit vielen auch gleichen Werten. Die Doppler sollen raus und das Ganze, wie auch immer(alphabetisch, usw...), sortiert werden.

        Ja, aber dann ergibt es IMO keinen Sinn, streng "numerisch" zu sortieren.

        Was passiert? Sortierung erfolgt nicht

        Doch, sicher. Nur nicht so, wie du es erwartest.
        Die Funktion heißt array_unique, also ist der primäre Zweck, Dubletten zu finden. Das Sortieren ist nicht der eigentliche Zweck der Funktion, sondern nur ein interner optionaler Zwischenschritt vor dem eigentlichen Filterlauf. Das Array, das als Ergebnis zurückgegeben wird, ist von dieser Sortierung offenbar nicht betroffen (ja, das finde ich auch verwirrend). Wenn du sortieren willst, verwende vorab eine der Sortierfunktionen, etwa array_sort().
        Ich halte es eh nicht für sinnvoll, dass array_unique() noch mit Sortier-Fähigkeiten ausgestattet wurde - das Ergebnis ist genau die Verblüffung, wie du sie jetzt erlebst. Aber solche unlogischen Lösungen gibt's in PHP häufig.

        PS: Wieso markierst du deine PHP-Debugausgaben hier als HTML?
        Weil es ja nur Browseroutput ist und kein PHP-Code. Aber wenn es hier anders gewünscht ist, mach ich das gerne demnächst als PHP ;-)

        Nein. Es ist ja auch kein PHP. Am besten nur als [code] ohne Sprachangabe.

        Ciao,
         Martin

        --
        Alle Tage sind gleich lang. Aber unterschiedlich breit.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Hallo,

          das weiß ich nicht. Ehrlich gesagt, ich hätte es auch nicht erwartet. Ich hätte auch gedacht, dass die Uniquification als erster Schritt abläuft, und erst im zweiten Schritt optional(!) die verbliebenen Werte sortiert werden.

          ja so hatte ich das auch verstanden, bis auf die Sortierung, die ja angeblich schon immer zu der Funktion gehört hat, also nicht optional.

          Andererseits: Wer numerisch sortiert, der erwartet numerische Werte. Nicht-numerische Einträge sollten dann also gar nicht vorkomemn bzw. in einer vorgelagerten Eingabeprüfung schon reklamiert worden sein. Wenn diese Einträge dann in der weiteren Verarbeitung unter den Tisch fallen, ist das gar nicht so falsch.

          Genau, würden die nichtnumerischen wegfallen, fände ich das zwar nicht im Sinne der Funktion aber zumindest plausibel.

          Nehmen wir mal den normalen Fall an, für den diese Funktion eigentlich konzipiert sein sollte:
          Du hast ein großes Array mit vielen auch gleichen Werten. Die Doppler sollen raus und das Ganze, wie auch immer(alphabetisch, usw...), sortiert werden.

          Ja, aber dann ergibt es IMO keinen Sinn, streng "numerisch" zu sortieren.

          Habe ich auch gar nicht vor, war nur ein unerwarteter Output beim Testen dieser Sortierung. Gewünscht ist die Sortierung nach regular oder string, doch da tut sich ja gar nichts.

          Ich halte es eh nicht für sinnvoll, dass array_unique() noch mit Sortier-Fähigkeiten ausgestattet wurde - das Ergebnis ist genau die Verblüffung, wie du sie jetzt erlebst. Aber solche unlogischen Lösungen gibt's in PHP häufig.

          Ja ohne Sortierfunktion, wäre array_unique unter diesen Umständen sicher sinnvoller, nur du kannst es dir gar nicht aussuchen. Die Sortierfunktion war und ist nicht optional, lediglich die Art der Sortierung. Um also auf Nummer Sicher zu gehen, bietet sich nur an, komplett auf diese Funktion zu verzichten und eine eigene zu nutzen.

          Unlogische Lösungen in PHP häufig? Kann ich jetzt glücklicherweise nicht bestätigen, was dann wohl bedeutet, mir ist Einiges entgangen. Somit wäre es sehr wissenswert, wenn Du ein paar Beispiele anbringen könntest.

          Nein. Es ist ja auch kein PHP. Am besten nur als [code] ohne Sprachangabe.

          Dafür gibt's aber <schreibfaul>keinen Button</schreibfaul> ;-)

        2. Lieber Martin,

          Die Funktion heißt array_unique, also ist der primäre Zweck, Dubletten zu finden. Das Sortieren ist nicht der eigentliche Zweck der Funktion,

          ganz meine Meinung!

          Wenn du sortieren willst, verwende vorab eine der Sortierfunktionen, etwa array_sort().

          Diese Funktion kannte ich bisher noch nicht...

          Liebe Grüße,

          Felix Riesterer.

          --
          ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
          1. Hallo Felix,

            Wenn du sortieren willst, verwende vorab eine der Sortierfunktionen, etwa array_sort().
            Diese Funktion kannte ich bisher noch nicht...

            bis eben kannte ich sie noch.
            Jetzt frage ich mich: Woher?
            Was habe ich da durcheinandergebracht?
            Halluziniere ich etwa?

            *grübel*
             Martin

            --
            Das Leben ist lebensgefährlich und endet meistens tödlich.
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(