2009-07-07 7 views
11

Это действительно эзотерический вопрос, но мне действительно интересно. Я использую usort впервые за многие годы, и меня особенно интересует, что именно происходит. Предположим, что у меня есть следующий массив:PHP USORT Параметры функции обратного вызова

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

Я мог сортировать это с usort:

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

Я не 100% ясно, о том, что происходит с двумя параметрами $ а и $ б. Каковы они и что они представляют. Я имею в виду, я мог предположить, что $ a представляет текущий элемент в массиве, но что именно происходит с этим? Что такое $ b?

Я мог бы увеличить мой массив, чтобы включить строки:

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

И выполните следующее:

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

И что бы отсортировать мои дочерние-массивы в алфавитном порядке, основываясь на [0] значение индекса. Но это не дает никакой ясности в отношении того, что такое $ a и $ b. Я знаю только, что соответствие шаблону я ищу.

Может ли кто-нибудь предложить некоторую ясность относительно того, что на самом деле происходит?

+0

+1 Я всегда думал то же самое. – alex

ответ

5

Чтобы отсортировать все, что вам нужно, чтобы сравнить два предмета и выяснить, подходит ли один из них другому. Это то, что вы предлагаете. Эта функция будет передана двумя элементами из вашего входного массива и возвращает порядок, в котором они должны быть.

Как только у вас есть средство для сравнения двух элементов, вы можете использовать алгоритм сортировки .

Если вы незнакомы, вам может понравиться, как простой наивный алгоритм, например bubblesort, будет использовать функцию сравнения.

За кулисами PHP использует quicksort.

+2

Я считаю, что Джонатан заинтересован в части «за кулисами». –

31

Точное определение $ a и $ b будет зависеть от алгоритма, используемого для сортировки массива. Чтобы отсортировать все, что у вас есть, чтобы сравнить два элемента, это то, для чего используется функция обратного вызова. Некоторые алгоритмы сортировки могут начинаться в любом месте массива, другие могут запускаться только в определенной части, поэтому нет , фиксированных, что означает в $ a и $ b, кроме двух элементов в массиве, которые необходимо сравнивать в соответствии с текущий алгоритм.

Этот метод может использоваться для пролить свет на используемый алгоритм PHP.

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

Выход

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

С выхода и, глядя на источник, мы можем видеть вид используется действительно quicksort реализации, проверьте Zend/zend_qsort.c в источнике PHP (связанный с версией немного старый, но не сильно изменился).

Он выбирает стержень в середине массива, в этом случае 18, тогда ему необходимо изменить порядок списка, чтобы все элементы, которые меньше (в зависимости от используемой функции сравнения), чем точка поворота, приходили перед точкой поворота и так, чтобы все элементы, большие, чем точка поворота, приходили после него, мы можем видеть, что это делает это, когда сначала сравнивает все с 18.

Некоторые дополнительные схематические пояснения.

 
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

Отличный ответ. Павлу было достаточно, и сначала. Поэтому я наградил его акцией. Я поддержал вас, хотя и ценю вашу тщательность. – Sampson

+7

Ради аргументов я бы предположил, что сначала не всегда лучше. Если второй ответ более совершенен, люди должны быть вознаграждены за то, что нашли время, чтобы полностью ответить на вопрос. – acrosman

0

usort() или uasort() есть людей-чувства ошибка на отсортированном результате. Смотрите фрагмент кода:

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

результат является:

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

Видите ли вы ошибку? Нет? Хорошо, позвольте мне объяснить это. Оригинальные три «9» эльмента находятся в ключевом порядке: 2,3,4. Но в результате три «9» элемента теперь находятся в ключевом порядке: 4,3,2, т. Е. Элементы с равным значением находятся в обратном ключевом порядке после сортировки.

Если элемент является единственным значением, как в приведенном выше примере, с нами все в порядке. Однако, если элемент является составной величиной, то это может вызвать ошибку в отношении человека. См. Другие сегменты кода. Мы для сортировки много точек по горизонтали, то есть сортировать их на основе возрастания х-координату порядок величины:

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

результат является:

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

Вы видите 'Я люблю Лару Крофт и Tombraider 'становится' I Croft Lara love and Tombraider '.

Я называю это ошибкой человека, потому что это зависит от того, какой случай вы используете, и как вы чувствуете, что его нужно сортировать в реальном мире, когда сравниваемые значения одинаковы.

Смежные вопросы