Параметры USOR обратной связи PHP USPR

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

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

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

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

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

Ответ 2

Точное определение $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 12, and that what it compares next if 
                         //you check the output.
Step 2b: (19,56);        //and do the same with the greater

Ответ 3

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, т.е. Элементы с равным значением находятся в порядке обратного ключа после сортировки.

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

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' становится я Croft Lara love и Tombraider.

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