Вопрос по php – Параметры функции обратного вызова USORT в PHP

11

Это действительно эзотерический вопрос, но мне действительно любопытно. Я использую 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. Что они, и что они представляют. Я имею в виду, я мог бы предположить, что $ 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. Я знаю только то, что соответствует шаблону, который я ищу.

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

+1 Я всегда думал одинаково. alex

Ваш Ответ

3   ответа
0

У usort () или uasort () естьhuman-feeling bug по отсортированному результату. Смотрите сегмент кода:

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

Вы видите & apos;I love Lara Croft and Tombraider& APOS; становится & apos;I Croft Lara love and Tombraider& APOS ;.

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

5

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

Если у вас есть возможность сравнить два элемента, вы можете использоватьsort-algorithm-of-your-choice.

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

За кулисами PHP используетбыстрая сортировка.

Я полагаю, что Джонатан заинтересован в "закулисной работе". часть.
31

Точное определение $ a и $ b будет зависеть от алгоритма, используемого для сортировки массива. Чтобы отсортировать что-либо, у вас должно быть средство для сравнения двух элементов, для чего используется функция обратного вызова. Некоторые алгоритмы сортировки могут начинаться в любом месте массива, другие могут запускаться только в определенной его части, поэтому нетfixed значение в $ 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
)

Исходя из вывода и глядя на источник, мы видим, что используемый вид действительнобыстрая сортировка реализация, проверьте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
Error: User Rate Limit Exceeded Sampson
Error: User Rate Limit Exceeded

Похожие вопросы