Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么usort(php)即使不返回整数也能工作?_Php_Sorting_Usort_Php Internals - Fatal编程技术网

为什么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]