2009-07-07 9 views
11

Dies ist eine wirklich esoterische Frage, aber ich bin wirklich neugierig. Ich benutze Usort heute zum ersten Mal seit Jahren, und mich interessiert besonders, was genau vor sich geht. Angenommen habe ich die folgende Array bekommt:PHP's USORT Callback Funktion Parameter

$myArray = array(1, 9, 18, 12, 56); 

Ich konnte diese Art mit usort:

usort($myArray, function($a, $b){ 
    if ($a == $b) return 0; 
    return ($a < $b) ? -1 : 1; 
}); 

Ich bin nicht 100% klar, was mit den beiden Parametern wird auf $ a und $ b. Was sind sie und was repräsentieren sie? Ich meine, ich könnte annehmen, dass $ a das aktuelle Element im Array darstellt, aber womit wird es verglichen? Was ist $ b?

Ich konnte meine Array erhöhen Strings enthalten:

$myArray = array(
    array("Apples", 10), 
    array("Oranges", 12), 
    array("Strawberries", 3) 
); 

und führen Sie die folgenden Schritte aus:

usort($myArray, function($a, $b){ 
    return strcmp($a[0], $b[0]); 
}); 

Und das würde mein Kind-Arrays in alphabetischer Reihenfolge auf den [0] Indexwert basierend sortieren. Aber das bietet keine Klarheit darüber, was $ a und $ b sind. Ich weiß nur, dass die Übereinstimmung dem Muster entspricht, nach dem ich suche.

Kann jemand Klarheit darüber geben, was tatsächlich stattfindet?

+0

+1 Ich dachte immer das Gleiche. – alex

Antwort

5

Um alles zu sortieren, müssen Sie zwei Elemente vergleichen und herausfinden, ob eines vor dem anderen steht. Das liefern Sie an usort. Diese Funktion wird an zwei Elemente Ihres Eingabearrays übergeben und gibt die Reihenfolge zurück, in der sie sich befinden sollen.

Sobald Sie zwei Elemente miteinander vergleichen können, können Sie Sortieralgorithmus-Ihrer-Wahl verwenden.

Wenn Sie nicht vertraut sind, möchten Sie vielleicht sehen, wie eine einfache naive Algorithmus wie bubblesort eine Vergleichsfunktion verwenden würde.

Hinter den Kulissen verwendet PHP eine quicksort.

+2

Ich glaube, Jonathan interessiert sich für den Teil "hinter den Kulissen". –

31

Die genaue Definition von $ a und $ b hängt vom Algorithmus ab, der zum Sortieren des Arrays verwendet wird. Um etwas zu sortieren, müssen Sie zwei Elemente miteinander vergleichen können. Dafür wird die Callback-Funktion verwendet. Einige Sortieralgorithmen können irgendwo im Array beginnen, andere können nur in einem bestimmten Teil davon beginnen, also gibt es keine feste Bedeutung in $ a und $ b anders als sie sind zwei Elemente im Array, die nach dem verglichen werden müssen aktueller Algorithmus.

Diese Methode kann verwendet werden, um herauszufinden, welchen Algorithmus PHP verwendet.

<?php 

$myArray = array(1, 19, 18, 12, 56); 

function compare($a, $b) { 
    echo "Comparing $a to $b\n"; 
    if ($a == $b) return 0; 
    return ($a < $b) ? -1 : 1; 
} 

usort($myArray,"compare"); 
print_r($myArray); 
?> 

Ausgabe

[email protected]:~$ php sort.php 
Comparing 18 to 19 
Comparing 56 to 18 
Comparing 12 to 18 
Comparing 1 to 18 
Comparing 12 to 1 
Comparing 56 to 19 
Array 
(
    [0] => 1 
    [1] => 12 
    [2] => 18 
    [3] => 19 
    [4] => 56 
) 

Vom Ausgang und Blick auf die Quelle, die wir die Art verwendet sehen kann, ist in der Tat eine quicksort Implementierung überprüfen Zend/zend_qsort.c in der PHP-Quelle (die Version verknüpft ist ein bisschen alt, aber hat sich nicht viel verändert).

Es wählt den Drehpunkt in der Mitte des Arrays, in diesem Fall 18, dann muss die Liste neu angeordnet werden, so dass alle Elemente, die weniger sind (entsprechend der Vergleichsfunktion) als der Drehpunkt vor dem Drehpunkt kommen und damit alle Elemente, die größer als der Drehpunkt sind, danach kommen, können wir es sehen, wenn es zuerst alles mit 18 vergleicht.

Einige weitere schematische Erklärung.

 
Step 0: (1,19,18,12,56); //Pivot: 18, 
Step 1: (1,12,18,19,56); //After the first reordering 
Step 2a: (1,12);   //Recursively do the same with the lesser, here 
         //pivot's 12, and that's what it compares next if 
         //you check the output. 
Step 2b: (19,56);  //and do the same with the greater 
+0

Ausgezeichnete Antwort. Pauls war ausreichend und zuerst. Deshalb habe ich ihm die Annahme zugesprochen. Ich habe jedoch Ihre upvoted und schätzen Sie Ihre Gründlichkeit. – Sampson

+7

Aus Gründen der Argumentation würde ich vorschlagen, dass zuerst nicht immer besser ist. Wenn die zweite Antwort vollständiger ist, sollten die Menschen dafür belohnt werden, dass sie sich die Zeit genommen haben, die Frage vollständig zu beantworten. – acrosman

0

usort() oder uasort() einen Mensch-Gefühl Bug auf sortierte Ergebnis. Siehe das Codesegment:

function xxx($a,$b) { if ($a==$b) return 0; else return $a<$b?-1:1; } 
$x=array(1=>10,2=>9,3=>9,4=>9,5=>6,6=>38); 
uasort($x,'xxx'); 
print_r($x); 

das Ergebnis:

Array ([5] => 6 [4] => 9 [3] => 9 [2] => 9 [1] => 10 [6] => 38) 

Sehen Sie den Fehler? Nein? Ok, lass es mich erklären. Die ursprünglichen drei '9' Elemente sind in der Reihenfolge: 2,3,4. Aber im Ergebnis sind die drei 9 Elemente jetzt in der Schlüsselreihenfolge: 4,3,2, d. H. Gleichwertelemente sind nach dem Sortieren in umgekehrter Reihenfolge.

Wenn das Element nur ein Wert ist, wie im obigen Beispiel, ist es für uns in Ordnung. Wenn es sich bei dem Element um einen zusammengesetzten Wert handelt, kann es jedoch zu einem menschlichen Fehler kommen. Sehen Sie sich andere Code-Segmente an. Wir sind horizontal viele Punkte zu sortieren, dh Art sie basierend auf aufsteigend Wert um x-Koordinate:

function xxx($a,$b) { if ($a['x']==$b['x']) return 0; else return $a['x']<$b['x']?-1:1; } 
$x=array(1=>array('x'=>1, 'v'=>'l'),2=>array('x'=>9, 'v'=>'love'), 
     3=>array('x'=>9, 'v'=>'Lara'),4=>array('x'=>9, 'v'=>'Croft'), 
     5=>array('x'=>15, 'v'=>'and'),6=>array('x'=>38, 'v'=>'Tombraider')); 
uasort($x,'xxx'); 
print_r($x); 

das Ergebnis:

Array ([1] => Array ([x] => 1 [v] => l) [4] => Array ([x] => 9 [v] => croft) 
      [3] => Array ([x] => 9 [v] => Lara) [2] => Array ([x] => 9 [v] => love) 
      [5] => Array ([x] => 15 [v] => and) [6] => Array ([x] => 38 [v] => Tombraider)) 

Sie sehen 'Ich liebe Lara Croft und Tombraider 'wird' I Croft Lara Liebe und Tombraider '.

Ich nenne es Mensch-Gefühl Bug weil es hängt davon ab, welchen Fall Sie verwenden und wie Sie es in der realen Welt sortiert sein sollte, wenn die verglichenen Werte gleich sind.