我刚刚读过那个问题 https://stackoverflow.com/q/9458652/576767关于奇怪的 php 行为,尽管我可以研究更多,但我还远远无法理解它。
我假设读者已经阅读了原始问题并且知道OP的代码块和示例,但简而言之,OP正在尝试比较这两个数组,虽然结果很好,但比较函数似乎被不规则地调用:
$chomik = new chomik('a');
$a = array(5, $chomik, $chomik, $chomik);
$b = array($chomik, 'b', 'c', 'd');
array_diff_uassoc($a, $b, 'compare');
文档 http://php.net/manual/en/function.array-diff-uassoc.php有点晦涩......但它确实指出:
如果第一个参数被认为是,则比较函数必须返回小于、等于或大于零的整数分别小于、等于或大于第二。
据我了解,这意味着compare()
函数应该更像这样:
function compare($a, $b) {
echo("$a : $b<br/>");
if($a === $b) return 0;
else if ($a > $b) return 1;
else return -1;
}
然而,这仍然给出了非常奇怪的结果,甚至有更多的“重复”
1 : 0
1 : 2
3 : 1
2 : 1
3 : 2
1 : 0
1 : 2
3 : 1
2 : 1
3 : 2
0 : 0
1 : 0
1 : 1
2 : 0
2 : 1
2 : 2
3 : 0
3 : 1
3 : 2
3 : 3
面对诸多质疑,我读取compat php函数 https://pear.php.net/reference/PHP_Compat-latest/__filesource/fsource_PHP_Compat__PHP_Compat-1.6.0a3CompatFunctionarray_diff_uassoc.php.html,检查实际发生的部分很有趣:
foreach ($args[0] as $k => $v) {
for ($i = 1; $i < $array_count; $i++) {
foreach ($args[$i] as $kk => $vv) {
if ($v == $vv) { // compare keys only if value are the same
$compare = call_user_func_array($compare_func, array($k, $kk));
if ($compare == 0) {
continue 3; // value should not be added to the result
}
}
}
}
$result[$k] = $v;
}
这是实际来源 https://github.com/php/php-src/blob/master/ext/standard/array.c#L3938 (per comment https://stackoverflow.com/questions/29421414/why-does-array-diff-uassoc-compares-keys-whose-value-do-not-match#comment47016778_29422485)
这段代码执行比较函数的方式不应该输出我们看到的结果。 Foreach 无法在键中来回移动(据我所知???),这里第一个键的顺序似乎就是这种情况:
1 : 2
3 : 1
2 : 1
此外,如果值不匹配,它不应该检查键,那么为什么要检查所有这些:
1 : 2
3 : 1
2 : 1
3 : 2
etc...
源码中最上面的foreach()怎么能通过key来回循环呢?!
为什么值不匹配的键仍然进行比较?
foreach 循环实际上是否继续执行,即使它们已经执行过continue
d?
这是并发的一个例子吗?可以以某种方式启动 call_user_func_array 并实际执行echo("$a : $b<br/>");
比较函数的顺序与它们“启动”的顺序不一样?