假设我想这样做:
$a = array_intersect_assoc(
array(
'key1' => array(
'key2' => 'value2'
),
'key3' => 'value3',
'key4' => 'value4'
),
array(
'key1' => array(
'key2' => 'some value not in the first parameter'
),
'key3' => 'another value'
)
);
var_dump( $a );
打印结果为:
数组 '键1'=> 大批 'key2' => 字符串'value2'(长度=6)
很明显,两个数组中与“key2”关联的值并不相同,但是
array_intersect_assoc()
仍然返回 'key2' => 'value2'
作为相交值。
这是
array_intersect_assoc()
的预期行为吗?
谢谢!
是的,这是预期的行为,因为比较是使用字符串表示形式完成的,并且该函数不会向下递归嵌套数组。来自手册:
仅当 (string) $elem1 === (string) $elem2 时,key => value 对中的两个值才被视为相等。换句话说,执行严格的类型检查,因此字符串表示形式必须相同。
如果您尝试使用
'key1' => 'Array'
与数组相交,您会得到相同的结果,因为数组的字符串表示形式始终是 'Array'
。
nleippe 的用户贡献的注释之一包含一个看起来很有前途的递归实现(我修改了第三行以对任何非数组值进行字符串比较):
function array_intersect_assoc_recursive(&$arr1, &$arr2) {
if (!is_array($arr1) || !is_array($arr2)) {
// return $arr1 == $arr2; // Original line
return (string) $arr1 == (string) $arr2;
}
$commonkeys = array_intersect(array_keys($arr1), array_keys($arr2));
$ret = array();
foreach ($commonkeys as $key) {
$ret[$key] =& array_intersect_assoc_recursive($arr1[$key], $arr2[$key]);
}
return $ret;
}
满足您需要的功能:
/**
* Get array intersect assoc recursive.
*
* @param mixed $value1
* @param mixed $value2
*
* @return array|bool
*/
function getArrayIntersectAssocRecursive(&$value1, &$value2)
{
if (!is_array($value1) || !is_array($value2)) {
return $value1 === $value2;
}
$intersectKeys = array_intersect(array_keys($value1), array_keys($value2));
$intersectValues = [];
foreach ($intersectKeys as $key) {
if (getArrayIntersectAssocRecursive($value1[$key], $value2[$key])) {
$intersectValues[$key] = $value1[$key];
}
}
return $intersectValues;
}
function array_key_match_recursive(array $main, array $other, $i = 0, &$result = []) {
foreach($main as $key => $value) {
$k = sprintf('%s%s', str_repeat('=', $i), $key);
if (!isset($other[$key])) {
$result[$k][] = 'not key';
}
if (!is_array($value) && empty($other[$key])) {
$result[$k][] = 'value empty';
}
if (is_array($value) && isset($other[$key])) {
array_key_match_recursive($value, $other[$key], ++$i, $result);
}
}
//return (bool) !$result;
return $result;
}
我的版本基于@BoltClock版本:
function array_intersect_assoc_recursive($arr1, $arr2) {
if (!is_array($arr1) || !is_array($arr2)) {
return $arr1;
}
$commonkeys = array_keys($arr1);
if (!array_key_exists('$', $arr2)){
$commonkeys = array_intersect(array_keys($arr1), array_keys($arr2));
}
$ret = array();
foreach ($commonkeys as $key) {
$ret[$key] = array_intersect_assoc_recursive($arr1[$key], array_key_exists('$', $arr2) ? $arr2['$'] : $arr2[$key]);
}
return $ret;
}
我使用此代码来过滤复杂数组内的数据
示例:
$filter = [
'channels' => [
'$' => [
'id' => 1,
'type' => 1,
'count' => 1
]
],
'user' => [
'id' => 1,
'type' => 1
]
];
$data = [
'user' => [
'id' => '1234',
'type' => true,
'counter' => 14,
],
'filteredField' => 4,
'channels' => [
['id' => '567', 'type' => 'other', 'count' => 1345, 'filteredField' => 5,],
['id' => '890', 'type' => 'other', 'count' => 5456, 'filteredField' => 7,],
],
];
print_r(array_intersect_assoc_recursive($data, $filter));