为什么array_udiff使用比较函数而不是谓词函数?

时间:2016-01-12 16:38:35

标签: php arrays

array_udiff使用回调函数计算两个数组之间的差异。但是,它需要比较函数而不是谓词函数。

比较函数将项目A与项目B进行比较。谓词函数只是确定项目A是否等于项目B.

排序函数通常需要比较函数来确定正确的排序。由于array_udiff只是计算差异,因此判断每对是否相等的谓词函数似乎就足够了。

为什么array_udiff使用比较函数而不是谓词函数?如果我使用谓词而不是重要吗?即我可以选择仅使用01返回值来表示不平等和平等,放弃-1可能性吗?这会对我的结果产生什么不利影响?

2 个答案:

答案 0 :(得分:5)

php_array_diff()的实现(为许多用户空间数组函数提供实现)通过重用大量内部比较函数来实现。

这是因为这些比较功能已经存在用于其他目的,并且满足手头所需的任务:确定两个项目是否相等。他们做了一些额外的工作是不重要的;重要的是需要考虑的代码相对减少。 (一个equals函数可以很容易地用比较函数或者作为一个单独的实体来编写,但是现在你有两个函数来完成同样的工作。)

实际实施也适用于sorting。因此,您需要使用适合排序的比较算法,否则您将获得意外结果。例如:

$a = [0, 1, 2, 3, 4, 5, 6];
$b = [4];

print_r(array_udiff($a, $b, function($x, $y) {
    return $x <=> $y; //Sorting comparison function, correct
}));

print_r(array_udiff($a, $b, function($x, $y) {
    return $x != $y; // Equality test, incorrect
}));

给出

Array //Sorting comparison function, correct
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [5] => 5
    [6] => 6
)
Array // Equality test, incorrect
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4 // equality test causes udiff to incorrectly include 4
    [5] => 5
    [6] => 6
)

原因是php_array_diff()使用的算法。基本上它是这样的:

  • 复制并排序所有输入数组
  • 将输出 OUT 设置为等于已排序的第一个输入数组
  • 对于 SRC 中的每个元素
    • V SRC
    • 中当前元素的值
    • 对于每个输入数组 A 从第二个开始
      • 请跳至 A 中的下一个元素,即&gt; V ,但请注意我们是否超过== V
      • 如果我们找到 V 的匹配项,请将其从 OUT 中删除。
      • 如果我们没有(因此它保留在输入数组中),请跳过 SRC ,直到我们有新的 V &gt; =当前的

因此,该算法依赖于所有被排序的输入,并使用该事实(和比较函数),因此它只需要检查每个输入数组中的每个元素一次。如果比较函数没有导致实际排序的数组,则算法失败并且您得到错误的结果。


HHVM可能会导致不同的结果,因为HHVM使用不同的排序算法。 HHVM使用pure quicksort,而PHP使用包含插入排序优化的quicksort implementation derived from llvm

通常,不同的排序算法通过不同的方式达到相同的解决方案。也就是说,不同的算法导致元素以不同的顺序,不同的时间和不同的量进行比较。在比较函数不正确的情况下,这会对数组的最终顺序产生很大影响。

答案 1 :(得分:0)

补充有序数组必须更便宜。没有排序,将需要O(m * n)时间。