为什么 array_uintersect() 比较 array1 和 array2、array1 和 array1 以及 array2 和 array2 之间的元素?
Why does array_uintersect() compare elements between array1 & array2, array1 & array1, and array2 & array2?
测试脚本
$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
)。
有人可以解释这种行为吗?
我不知道为什么除了比较数组的值之外,您对比较回调有任何期望。回调的唯一目的是比较两个数组中的下一对项目。
函数returns两个数组相交的结果。在回调中,您表达了应该如何比较这些值的想法。例如,下面的代码假设应该通过比较字符串的第一个字符来执行交集:
$a = array_uintersect(['foo', 'bar'], ['baz', 'qux'], function($a, $b) {
return strcmp($a[0], $b[0]);
});
print_r($a);
输出
Array
(
[1] => bar
)
传递给回调的项目顺序由 PHP 内部指定,将来可能很容易更改。
所以比较函数不应该做任何事情,除了比较两个变量。在官方文档中甚至没有暗示将回调用于任何其他目的。
我相信前两个调用被用来为内部算法中的变量播种。但是由于您没有 return 任何算法可以用来确定 equality/sorting 的东西,它只运行接下来的两个。
如果您实际上 return 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
)
<?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)
我想你正在找这个 ;)
$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"
}
}
更新:它 returns 使用 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)
}
}
array_uintersect
docs is that, internally, PHP sorts all the arrays中没有提到的先从左到右。只有 在 数组排序后 PHP 遍历它们(再次从左到右)以找到交集。
第三个参数(比较函数)被传递给内部排序算法,而不是相交算法。因此,看到的调试输出是确定排序的排序算法。
zend_sort implementation generally uses a bisecting quick sort implementation. For arrays of the size in your example, PHP uses insertion sort. For large arrays, PHP uses a 3 or 5 point pivot so as to improve worst-case complexity.
由于您没有显式地从比较函数返回任何值,PHP 默认返回 null (0),并且由于 PHP 使用插入排序,您看到 O( n*n) 排序遍历所有组合时的行为。
测试脚本
$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
)。
有人可以解释这种行为吗?
我不知道为什么除了比较数组的值之外,您对比较回调有任何期望。回调的唯一目的是比较两个数组中的下一对项目。
函数returns两个数组相交的结果。在回调中,您表达了应该如何比较这些值的想法。例如,下面的代码假设应该通过比较字符串的第一个字符来执行交集:
$a = array_uintersect(['foo', 'bar'], ['baz', 'qux'], function($a, $b) {
return strcmp($a[0], $b[0]);
});
print_r($a);
输出
Array
(
[1] => bar
)
传递给回调的项目顺序由 PHP 内部指定,将来可能很容易更改。
所以比较函数不应该做任何事情,除了比较两个变量。在官方文档中甚至没有暗示将回调用于任何其他目的。
我相信前两个调用被用来为内部算法中的变量播种。但是由于您没有 return 任何算法可以用来确定 equality/sorting 的东西,它只运行接下来的两个。
如果您实际上 return 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
)
<?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)
我想你正在找这个 ;)
$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"
}
}
更新:它 returns 使用 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)
}
}
array_uintersect
docs is that, internally, PHP sorts all the arrays中没有提到的先从左到右。只有 在 数组排序后 PHP 遍历它们(再次从左到右)以找到交集。
第三个参数(比较函数)被传递给内部排序算法,而不是相交算法。因此,看到的调试输出是确定排序的排序算法。
zend_sort implementation generally uses a bisecting quick sort implementation. For arrays of the size in your example, PHP uses insertion sort. For large arrays, PHP uses a 3 or 5 point pivot so as to improve worst-case complexity.
由于您没有显式地从比较函数返回任何值,PHP 默认返回 null (0),并且由于 PHP 使用插入排序,您看到 O( n*n) 排序遍历所有组合时的行为。