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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top