这是一个非常深奥的问题,但我真的很好奇。今天是我多年来第一次使用 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 是什么。我只知道它符合我正在寻找的模式。

有人可以澄清一下实际发生的事情吗?

有帮助吗?

解决方案

要排序任何你需要比较两个项目,并计算出如果一个人到来之前其他的手段。这是你提供什么usort。该功能会从您的输入数组传递两个项目,并返回顺序它们应该在

一旦你要比较两个元素的方式,你可以使用的排序算法 - 的 - 你选的。

如果您不熟悉,你可能会想看看如何将一个简单天真的算法如冒泡将使用比较函数。

在幕后,PHP是使用快速排序

其他提示

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

输出

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
)

从输出和查看源代码我们可以看到使用的排序确实是 快速排序 实施,检查 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

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” elments按键顺序排序: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 ) )

您看到 ' 我爱劳拉和古墓丽影' 变成了 ' 我克罗夫特拉拉爱和古墓丽影'

我称之为人类感觉的错误,因为它取决于你用什么情况下,你的感觉如何,应该在现实世界中进行排序时比较值相同。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top