2009-07-07 26 views
11

Esta es una pregunta realmente esotérica, pero estoy realmente curioso. Estoy usando usort por primera vez hoy en años, y estoy particularmente interesado en qué está sucediendo exactamente. Supongamos que tengo la siguiente matriz:Parámetros de la función de devolución de llamada USORT PHP

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

que podía resolver esto con usort:

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

no estoy 100% claro acerca de lo que está pasando con los dos parámetros de $ a $ y segundo. ¿Qué son y qué representan? Quiero decir, podría suponer que $ a representa el elemento actual en el conjunto, pero ¿con qué exactamente se compara esto? ¿Qué es $ b?

pude aumentar mi matriz para incluir cadenas:

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

y ejecute los siguientes:

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

Y eso lo solucionaría mi hijo-arrays alfabéticamente en base a la [0] valor del índice. Pero esto no ofrece ninguna claridad sobre lo que son $ a y $ b. Solo sé que coinciden con el patrón que estoy buscando.

¿Alguien puede aportar algo de claridad sobre lo que realmente está ocurriendo?

+0

+1 Siempre he pensado lo mismo. – alex

Respuesta

5

Para ordenar todo lo que necesita un medio para comparar dos elementos y averiguar si uno viene antes que el otro. Esto es lo que le proporciona a usort. Esta función recibirá dos elementos de su matriz de entrada y devolverá el orden en que deberían estar.

Una vez que tenga un medio para comparar dos elementos, puede usar ordenar-algoritmo-de-su-elección.

Si no está familiarizado, le gustaría ver cómo un simple algoritmo ingenuo como bubblesort usaría una función de comparación.

Detrás de escena, PHP está utilizando un quicksort.

+2

Creo que Jonathan está interesado en la parte "detrás de escena". –

31

La definición exacta de $ a y $ b dependerá del algoritmo utilizado para ordenar la matriz. Para ordenar todo lo que tiene que tener un medio para comparar dos elementos, para eso se usa la función de devolución de llamada. Algunos algoritmos de clasificación pueden comenzar en cualquier parte de la matriz, otros solo pueden comenzar en una parte específica de la misma, por lo que no hay fijo que signifique en $ a y $ b que no sean dos elementos de la matriz que deben compararse de acuerdo con el algoritmo actual.

Este método se puede utilizar para arrojar luz sobre qué algoritmo PHP está utilizando.

<?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); 
?> 

salida

[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 
) 

Desde la salida y mirando a la fuente podemos ver el tipo utilizado es de hecho una aplicación quicksort, comprobar si hay Zend/zend_qsort.c en el código fuente de PHP (la vinculada a la versión es un poco viejo, pero no ha cambiado mucho).

Toma el pivote en el centro del conjunto, en este caso 18, luego necesita reordenar la lista para que todos los elementos que son menos (según la función de comparación en uso) que el pivote lleguen antes del pivote y para que todos los elementos superiores al pivote vengan después, podemos verlo haciendo eso cuando al principio todo se compara con 18.

Alguna otra explicación diagramática.

 
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

Excelente respuesta. Paul's fue suficiente, y primero. Por lo tanto, le concedí la aceptación. Sin embargo, he votado el tuyo y aprecio tu minuciosidad. – Sampson

+7

Por el bien del argumento, sugeriría que primero no siempre es mejor. Si la segunda respuesta es más completa, las personas deberían ser recompensadas por tomarse el tiempo para responder la pregunta por completo. – acrosman

0

usort() o uasort() tiene un error -sentimiento humano en de resultados ordenados. Ver el segmento de código:

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); 

el resultado es:

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

Cómo ves el error? ¿No? Ok, déjame explicarte. Los tres elementos originales '9' están en orden clave: 2,3,4. Pero en el resultado, los tres elementos '9' ahora están en orden clave: 4,3,2, es decir, los elementos de igual valor están en orden inverso a la clave después de la clasificación.

Si el elemento tiene un solo valor, como en el ejemplo anterior, está bien para nosotros. Sin embargo, si el elemento tiene un valor compuesto, puede causar un error humano. Ver otros segmentos de código. Estamos para solucionar muchos puntos en horizontal, es decir, una especie de ellos basado en ascendente coordenada x orden de valores:

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); 

el resultado es:

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)) 

Ves 'Me encanta Lara Croft y Tombraider 'se convierte en' I Croft Lara love y Tombraider '.

Lo llamo error de sensación humana porque depende de qué caso utilice y cómo cree que debería ordenarse en el mundo real cuando los valores comparados son los mismos.

Cuestiones relacionadas