PHP问题:如何递归数组_intersect_assoc()

yr9zkbsy  于 2022-10-30  发布在  PHP
关注(0)|答案(4)|浏览(145)

假设我想这样做:

$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 );

打印结果为:

array
  'key1' => 
    array
      'key2' => string 'value2' (length=6)

很明显,两个数组中与“key 2”关联的值是不同的,但是array_intersect_assoc()仍然返回'key2' => 'value2'作为相交的值。
这是array_intersect_assoc()的预期行为吗?
谢谢你!

b09cbbtk

b09cbbtk1#

是的,这是预期的行为,因为比较是使用字符串表示来完成的,并且函数不会向下递归嵌套数组。
只有当 (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;
}
quhf5bfb

quhf5bfb2#

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;
}
e4eetjau

e4eetjau3#

一个可以满足您需要的函数:

/**
 * Get array intersect assoc recursive.
 *
 * @param mixed $value1
 * @param mixed $value2
 *
 * @return array|bool
 */
function getArrayIntersectAssocRecursive(&$value1, &$value2)
{
    if (!is_array($value1) || !is_array($value1)) {
        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;
}
8ulbf1ek

8ulbf1ek4#

我的版本基于@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));

在线测试:https://onlinephp.io/c/3be04

相关问题