试图理解array_diff_uassoc优化

时间:2015-03-04 04:47:30

标签: php arrays sorting php-7

似乎数组在array_diff_uassoc内相互比较之前已经排序。

这种方法有什么好处?

测试脚本

function compare($a, $b)
    {
    echo("$a : $b\n");
    return strcmp($a, $b);
    }

$a = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
$b = array('v' => 1, 'w' => 2, 'x' => 3, 'y' => 4, 'z' => 5);
var_dump(array_diff_uassoc($a, $b, 'compare'));


$a = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
$b = array('d' => 1, 'e' => 2, 'f' => 3, 'g' => 4, 'h' => 5);
var_dump(array_diff_uassoc($a, $b, 'compare'));


$a = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
$b = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
var_dump(array_diff_uassoc($a, $b, 'compare'));

$a = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
$b = array('e' => 5, 'd' => 4, 'c' => 3, 'b' => 2, 'a' => 1);
var_dump(array_diff_uassoc($a, $b, 'compare'));

http://3v4l.org/DKgms#v526

P.S。似乎排序算法在php7中发生了变化。

2 个答案:

答案 0 :(得分:4)

排序算法在PHP 7中没有改变。元素只是以另一个顺序传递给排序算法以进行一些性能改进。

嗯,好处可能是最终更快的执行。当两个阵列都有其他密钥时,你真的遇到了最坏的情况。

最坏情况复杂性是对数组进行两次排序,然后比较两个数组的每个键。 O(n*m + n * log(n) + m * log(m))

最好的情况是两次排序,然后与较小数组中的元素一样多的比较。 O(min(m, n) + n * log(n) + m * log(m))

如果匹配,您不必再次与完整数组进行比较,而只需在匹配后从键中进行比较。

但在目前的实施中,排序只是多余的。我认为php-src中的实现需要一些改进。没有彻头彻尾的错误,但实施很糟糕。如果你理解了一些C:http://lxr.php.net/xref/PHP_TRUNK/ext/standard/array.c#php_array_diff (请注意,该功能是通过php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);

中的array_diff_uassoc调用的

答案 1 :(得分:3)

理论

排序允许进行一些快捷方式;例如:

A      | B
-------+------
1,2,3  | 4,5,6

A的每个元素只会与B [0]进行比较,因为已知其他元素至少相同。

另一个例子:

A      | B
-------+-------
4,5,6  | 1,2,6

在这种情况下,A [0]与B的所有元素进行比较,但A [1]和A [2]仅与B [2]进行比较。

如果A的任何元素大于B中的所有元素,那么你将获得最差的表现。

实践

虽然上述内容适用于标准array_diff()array_udiff(),但一旦使用了密钥比较函数,由于this change尝试时会产生O(n * m)性能修复this bug

上述错误描述了自定义键比较函数在与具有混合键的数组(即数字键和字符串键值)一起使用时如何导致意外结果。我个人认为这应该通过文档解决,因为ksort()会得到同样奇怪的结果。