Parâmetros de função de retorno de chamada do PHP
Pergunta
Esta é uma pergunta realmente esotérica, mas estou genuinamente curioso. Estou usando a USORT pela primeira vez hoje em anos e estou particularmente interessado no que exatamente está acontecendo. Suponha que eu tenho a seguinte matriz:
$myArray = array(1, 9, 18, 12, 56);
Eu poderia resolver isso com nós:
usort($myArray, function($a, $b){
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
});
Não estou 100% claro sobre o que está acontecendo com os dois parâmetros $ A e $ B. O que eles são e o que eles representam. Quero dizer, eu poderia assumir que $ A representa o item atual na matriz, mas o que exatamente isso está sendo comparado? O que é $ B?
Eu poderia aumentar minha matriz para incluir strings:
$myArray = array(
array("Apples", 10),
array("Oranges", 12),
array("Strawberries", 3)
);
E execute o seguinte:
usort($myArray, function($a, $b){
return strcmp($a[0], $b[0]);
});
E isso classificaria meu filho-marca em ordem alfabeticamente com base no valor [0] do índice. Mas isso não oferece nenhuma clareza sobre o que $ A e $ B são. Só sei que a correspondência do padrão que estou procurando.
Alguém pode oferecer alguma clareza sobre o que realmente está ocorrendo?
Solução
Para classificar qualquer coisa, você precisa de um meio para comparar dois itens e descobrir se um vier antes do outro. É isso que você fornece para nós. Esta função será passada dois itens da sua matriz de entrada e retornará o pedido em que deve estar.
Depois de ter um meio de comparar dois elementos, você pode usar Sort-algoritmo de sua escolha.
Se você não estiver familiar Tipo de bolha usaria uma função de comparação.
Nos bastidores, o PHP está usando um ordenação rápida.
Outras dicas
A definição exata de $ A e $ B dependerá do algoritmo usado para classificar a matriz. Para classificar qualquer coisa que você precise ter um meio de comparar dois elementos, é para isso que a função de retorno de chamada é usada. Alguns algoritmos de classificação podem começar em qualquer lugar da matriz, outros podem começar apenas em uma parte específica, para que não haja fixo Significado em $ A e $ B, além de dois elementos na matriz que precisam ser comparados de acordo com o algoritmo atual.
Este método pode ser usado para lançar luz sobre a qual o algoritmo PHP está usando.
<?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);
?>
Resultado
vinko@mithril:~$ 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
)
Da saída e olhando para a fonte, podemos ver o tipo usado é realmente um ordenação rápida implementação, verifique se há Zend/zend_qsort.c Na fonte PHP (a versão vinculada é um pouco antiga, mas não mudou muito).
Ele escolhe o pivô no meio da matriz, neste caso 18, então precisa reordenar a lista para que todos os elementos que sejam menores (de acordo com a função de comparação em uso) do que o pivô vêm antes do pivô e para que todos Elementos maiores que o pivô vêm depois, podemos ver isso quando compara tudo com 18 a princípio.
Algumas explicações diagramáticas adicionais.
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
usort () ou uasort () têm um Bug sensível ao humano em resultado classificado. Veja o 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);
o resultado é:
Array ( [5] => 6 [4] => 9 [3] => 9 [2] => 9 [1] => 10 [6] => 38 )
Você vê o bug? Não? Ok, deixe -me explicar. Os três '9' originais estão em ordem -chave: 2,3,4. Mas, no resultado, os três elementos '9' estão agora em ordem-chave: 4,3,2, ou seja, elementos de valor igual estão em ordem chave reversa após a classificação.
Se o elemento for apenas um valor único, como no exemplo acima, tudo bem conosco. No entanto, se o elemento for valor composto, poderá causar um bug humano. Veja outros segmentos de código. Devemos classificar muitos pontos horizontalmente, ou seja, classificá-los com base em uma ordem de valor de coordenada x ascendente:
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);
o resultado é:
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 ) )
Você vê 'Eu amo Lara Croft e Tombraider' torna-se 'Eu amo Lara Lara e Tombraider'.
Eu chamo isso Bug sensível ao humano Porque depende do caso que você usa e de como se sente, deve ser classificado no mundo real quando os valores comparados são os mesmos.