测试脚本
$i = 0;
array_uintersect(['foo', 'bar'], ['baz', 'qux'], function($a, $b) use (&$i) {
print_r([$a, $b, $i++]);
});
实际结果
Array
(
[0] => bar
[1] => foo
[2] => 0
)
Array
(
[0] => qux
[1] => baz
[2] => 1
)
Array
(
[0] => bar
[1] => qux
[2] => 2
)
Array
(
[0] => bar
[1] => foo
[2] => 3
)
预期结果
Array
(
[0] => foo
[1] => baz
[2] => 0
)
Array
(
[0] => bar
[1] => qux
[2] => 1
)
换句话说,我期望传递给回调的是左数组的当前元素和右数组的当前元素。
此外,如果我将另一个数组传递给array_uintersect
,我希望应用相同的逻辑 - 例如,将另一个参数传递给回调($c
)。
有人可以解释这种行为吗?
答案 0 :(得分:2)
我不知道除了比较数组的值之外,你为什么期望比较回调中的任何东西。回调的唯一目的是比较两个数组中的下一对项目。
该函数返回两个数组的交集结果。在回调中,您表达了如何比较值的想法。例如,以下代码假定应通过比较字符串的第一个字符来执行交集:
$a = array_uintersect(['foo', 'bar'], ['baz', 'qux'], function($a, $b) {
return strcmp($a[0], $b[0]);
});
print_r($a);
输出
Array
(
[1] => bar
)
传递给回调的项的顺序由PHP内部指定,并且将来可能很容易改变。
因此除了比较两个变量之外,比较函数不应该做任何事情。在官方文档中,任何其他目的都没有使用回调的暗示。
答案 1 :(得分:1)
我相信前两个调用用于在内部算法中为变量设定种子。但是既然你没有返回算法可以用来确定相等/排序的任何东西,那么它只运行接下来的两个。
如果您实际返回0
,1
或-1
,那么您会看到计算交叉点所需的完整比较链:
$i = 0;
array_uintersect(['foo', 'bar'], ['baz', 'qux'], function($a, $b) use (&$i) {
print_r([$a, $b, $i++]);
if ($a === $b) return 0;
if ($a > $b) return 1;
return -1;
});
收率:
Array
(
[0] => bar
[1] => foo
[2] => 0
)
Array
(
[0] => qux
[1] => baz
[2] => 1
)
Array
(
[0] => bar
[1] => baz
[2] => 2
)
Array
(
[0] => foo
[1] => baz
[2] => 3
)
Array
(
[0] => foo
[1] => baz
[2] => 4
)
Array
(
[0] => foo
[1] => qux
[2] => 5
)
答案 2 :(得分:1)
array_uintersect
docs中未提及的内容是PHP sorts all the arrays首先从左到右。只有在数组排序后,PHP才会将它们(再次,从左到右)移动以找到交集。
第三个参数(比较函数)传递给内部排序算法,而不是交叉算法。因此,看到的调试输出是计算排序的排序算法。
zend_sort implementation通常使用uses a bisecting quick sort implementation。对于示例中大小的数组,PHP使用插入排序。对于大型数组,PHP使用3或5点的轴,以便improve worst-case complexity。
由于您没有显式地从比较函数返回任何值,因此PHP默认返回null(0),并且由于PHP使用插入排序,因此您会看到O(n * n)行为,因为排序所有组合。
答案 3 :(得分:0)
我认为你正在寻找这个;)
$result = array_map(function($a, $b) {
return [$a, $b];
}, ['foo', 'bar'], ['baz', 'qux']);
var_dump($result);
这将输出
array(2) {
[0]=>
array(2) {
[0]=>
string(3) "foo"
[1]=>
string(3) "baz"
}
[1]=>
array(2) {
[0]=>
string(3) "bar"
[1]=>
string(3) "qux"
}
}
更新:它使用array_uintersect
方法返回您想要的结果。它不是最有效的方法,并且没有使用不同的数据集等进行测试但是应该可以工作。
$entities = [
[
'id' => 1,
'timestamp' => 1234
],
[
'id' => 2,
'timestamp' => 12345
],
[
'id' => 3,
'timestamp' => 123456
],
[
'id' => 8,
'timestamp' => 123456
],
[
'id' => 10,
'timestamp' => 123456
],
[
'id' => 11,
'timestamp' => 123456
],
[
'id' => 12,
'timestamp' => 123456
]
];
$identities = [1, 11, 2, 8, 10];
$result = array_uintersect($entities, $identities, function($a, $b) {
// Both array skip
if (is_array($a) && is_array($b)) {
if ($a['id'] > $b['id']) {
return 1;
}
return -1;
}
// Both int skip
if (is_int($a) && is_int($b)) {
if ($a > $b) {
return 1;
}
return -1;
}
// $a is array
if (is_array($a)) {
if ($a['id'] == $b) {
return 0;
}
elseif ($a['id'] > $b) {
return 1;
}
return -1;
}
// $b is array
if($b['id'] == $a) {
return 0;
}
if($a > $b['id']) {
return 1;
}
return -1;
});
var_dump($result);
和结果
array(5) {
[0]=>
array(2) {
["id"]=>
int(1)
["timestamp"]=>
int(1234)
}
[1]=>
array(2) {
["id"]=>
int(2)
["timestamp"]=>
int(12345)
}
[3]=>
array(2) {
["id"]=>
int(8)
["timestamp"]=>
int(123456)
}
[4]=>
array(2) {
["id"]=>
int(10)
["timestamp"]=>
int(123456)
}
[5]=>
array(2) {
["id"]=>
int(11)
["timestamp"]=>
int(123456)
}
}
答案 4 :(得分:-4)
<?php
$i = 0;
$r1 = ['foo', 'bar'];
$r2 = ['baz', 'qux'];
$result = array_uintersect($r1, $r2, function($a, $b){
return ($a[0]> $b[0]);
});
var_dump($result);
// YIELDS::
array (size=2)
0 => string 'foo' (length=3)
1 => string 'bar' (length=3)