为什么usort(php)即使不返回整数也能工作?
昨天在工作中,我偶然发现了一段大致如下的代码:为什么usort(php)即使不返回整数也能工作?,php,sorting,usort,php-internals,Php,Sorting,Usort,Php Internals,昨天在工作中,我偶然发现了一段大致如下的代码: uasort($array, function($a, $b) { return isset($a['sort_code']) && isset($b['sort_code']) && $a['sort_code'] > $b['sort_code']; }); 这在我脑海中翻转了几个开关,因为这只能返回布尔值true或false,而不是php.net中明确规定的0 1或-1。最佳情况下,PHP将fa
uasort($array, function($a, $b) {
return isset($a['sort_code']) && isset($b['sort_code']) && $a['sort_code'] > $b['sort_code'];
});
这在我脑海中翻转了几个开关,因为这只能返回布尔值true或false,而不是php.net中明确规定的0 1或-1。最佳情况下,PHP将false解释为0,true解释为1。因此,一位(写这篇文章的同事)可能会争辩说它确实有效
我认为它不可能工作,因为它永远不会返回-1。排序回调的返回中缺少一个状态true或false,我认为您可能会得到错误的结果,或者进程性能不佳
实际上我已经开始写一些测试了,虽然我不是排序专家,但实际上我已经到了一个地步,你可以去掉-1状态,并且仍然得到一个正确的排序,计算量相同
实际上,您可以替换:
if ($a === $b) {
return 0;
}
return $a < $b ? -1 : 1;
现在,正如我所说,我决不是一个分类专家,我的测试也不够彻底。然而,我对小型和大型阵列的结果表明,这是正确的。无论使用哪种方法,数组总是正确排序,并且计算量相同
因此,没有第三种状态(-1)似乎真的没什么大不了的
我仍然坚持我的观点,你应该严格遵循文档,尤其是PHP。当php说我需要0、负数或正数时,这正是我们应该做的。你不应该把这样的事情留给偶然的机会,看事情是如何在偶然的情况下运作的
然而,我对这一切都很感兴趣,我想从一些了解更多的人那里得到一些见解
想法?有人吗?您不必实际返回全部-1、0和1,函数才能工作。返回0不会在适当的位置切换元素。还可以返回类似-1345的值作为-1 仅返回0或1意味着您只想将某些元素“下沉”到数组的末尾,例如在数组的末尾或开头有all
NULL
值,其他排序并不重要:
$input = ['c', 'a', null, 'b', null];
usort($input, function ($a, $b) {
return !is_null($b);
});
// 'b', 'a', 'c', null, null
var_dump($input);
在您的情况下,它是对元素进行排序,而不以
sort\u code
结尾,也不以sort\u code的顺序进行排序uasort()
中的逻辑适合于进行较少的总体比较,因此(假设排序规则提供预期结果)执行效率更高
据我所知,PHP的uasort()
使用了,但是文档说你不应该依赖这一事实(也许将来会发生变化)。安
下面是一个示例,它表明sort调用只进行了足够的比较,可能会破坏所有关系。由于需要进行更多的比较,但由于排序指令的原因,可能会产生不同的排序,因此采用三向比较的成本更高
$array = [
['id' => 1, 'sort_code' => 4],
['id' => 2, 'sort_code' => 2],
['id' => 3],
['id' => 4, 'sort_code' => 8],
['id' => 5],
['id' => 6, 'sort_code' => 6]
];
uasort($array, function($a, $b) {
echo "\n({$a['id']} -vs- {$b['id']}) " , ($a['sort_code'] ?? 'undeclared') , " -vs- " , ($b['sort_code'] ?? 'undeclared') , " eval: ";
echo $eval = (int)(isset($a['sort_code']) && isset($b['sort_code']) && $a['sort_code'] > $b['sort_code']);
return $eval;
});
echo "\n---\n";
var_export($array);
echo "\n======\n";
uasort($array, function($a, $b) {
echo "\n({$a['id']} -vs- {$b['id']}) " , ($a['sort_code'] ?? 'undeclared') , " -vs- " , ($b['sort_code'] ?? 'undeclared') , " eval: ";
echo $eval = (int)(($a['sort_code'] ?? 0) <=> ($b['sort_code'] ?? 0));
return $eval;
});
echo "\n---\n";
var_export($array);
A只需要一个总的前序,这基本上是一个“小于或等于”关系。换句话说,a$array = [
['id' => 1, 'sort_code' => 4],
['id' => 2, 'sort_code' => 2],
['id' => 3],
['id' => 4, 'sort_code' => 8],
['id' => 5],
['id' => 6, 'sort_code' => 6]
];
uasort($array, function($a, $b) {
echo "\n({$a['id']} -vs- {$b['id']}) " , ($a['sort_code'] ?? 'undeclared') , " -vs- " , ($b['sort_code'] ?? 'undeclared') , " eval: ";
echo $eval = (int)(isset($a['sort_code']) && isset($b['sort_code']) && $a['sort_code'] > $b['sort_code']);
return $eval;
});
echo "\n---\n";
var_export($array);
echo "\n======\n";
uasort($array, function($a, $b) {
echo "\n({$a['id']} -vs- {$b['id']}) " , ($a['sort_code'] ?? 'undeclared') , " -vs- " , ($b['sort_code'] ?? 'undeclared') , " eval: ";
echo $eval = (int)(($a['sort_code'] ?? 0) <=> ($b['sort_code'] ?? 0));
return $eval;
});
echo "\n---\n";
var_export($array);
(1 -vs- 2) 4 -vs- 2 eval: 1
(1 -vs- 3) 4 -vs- undeclared eval: 0
(3 -vs- 4) undeclared -vs- 8 eval: 0
(4 -vs- 5) 8 -vs- undeclared eval: 0
(5 -vs- 6) undeclared -vs- 6 eval: 0
---
array (
1 =>
array (
'id' => 2,
'sort_code' => 2,
),
0 =>
array (
'id' => 1,
'sort_code' => 4,
),
2 =>
array (
'id' => 3,
),
3 =>
array (
'id' => 4,
'sort_code' => 8,
),
4 =>
array (
'id' => 5,
),
5 =>
array (
'id' => 6,
'sort_code' => 6,
),
)
======
(2 -vs- 1) 2 -vs- 4 eval: -1
(1 -vs- 3) 4 -vs- undeclared eval: 1
(2 -vs- 3) 2 -vs- undeclared eval: 1
(1 -vs- 4) 4 -vs- 8 eval: -1
(4 -vs- 5) 8 -vs- undeclared eval: 1
(1 -vs- 5) 4 -vs- undeclared eval: 1
(2 -vs- 5) 2 -vs- undeclared eval: 1
(3 -vs- 5) undeclared -vs- undeclared eval: 0
(4 -vs- 6) 8 -vs- 6 eval: 1
(1 -vs- 6) 4 -vs- 6 eval: -1
---
array (
2 =>
array (
'id' => 3,
),
4 =>
array (
'id' => 5,
),
1 =>
array (
'id' => 2,
'sort_code' => 2,
),
0 =>
array (
'id' => 1,
'sort_code' => 4,
),
5 =>
array (
'id' => 6,
'sort_code' => 6,
),
3 =>
array (
'id' => 4,
'sort_code' => 8,
),
)
$array = [
['sort_code' => 2],
[],
['sort_code' => 1]
];
uasort($array, function($a, $b) {
return isset($a['sort_code']) && isset($b['sort_code']) && $a['sort_code'] > $b['sort_code'];
});
var_export($array);
array (
0 =>
array (
'sort_code' => 2,
),
1 =>
array (
),
2 =>
array (
'sort_code' => 1,
),
)
$array[0] <= $array[1]
$array[1] <= $array[2]
$array[0] > $array[2]
$array[0] <= $array[2]