【问题标题】:PHP Question: how to array_intersect_assoc() recursivelyPHP问题:如何递归地array_intersect_assoc()
【发布时间】:2011-06-05 08:28:15
【问题描述】:

假设我想这样做:

$a = array_intersect_assoc( 大批( 'key1' => 数组( 'key2' => 'value2' ), 'key3' => 'value3', 'key4' => 'value4' ), 大批( 'key1' => 数组( 'key2' => '第一个参数中没有的值' ), 'key3' => '另一个值' ) ); var_dump($a);

打印出来的结果是:

大批 'key1' => 大批 'key2' => 字符串'value2'(长度=6)

很明显,两个数组中与 'key2' 关联的值并不相同,但 array_intersect_assoc() 仍然返回 'key2' => 'value2' 作为相交值。

这是array_intersect_assoc() 的预期行为吗?

谢谢!

【问题讨论】:

  • 这太棒了!特别是因为array('key2' => 'value2') == array('key2' => 'some value not in the first parameter') === false,而array('key2' => 'value2') == array('key2' => 'value2') === true。当我说:嗯。

标签: php arrays multidimensional-array


【解决方案1】:

是的,这是预期的行为,因为比较是使用字符串表示完成的,并且该函数不会递归嵌套数组。来自manual

仅当 (string) $elem1 === (string) $elem2 时,key => value 对中的两个值才被视为相等。换句话说,执行严格的类型检查,因此字符串表示形式必须相同。

如果您尝试与带有'key1' => 'Array' 的数组相交,您会得到相同的结果,因为数组的字符串表示始终是'Array'

One of the user-contributed notes,由 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;
}

【讨论】:

  • 谢谢!现在一切都说得通了:)
  • 我已经更新了后者的实现,使其具有更主流的向后兼容性php.net/manual/en/function.array-intersect-assoc.php#111707
  • 上述函数对我有用,但我不得不删除 & 以防止在 Ubuntu 16.04 上的 PHP 5.6.30 中出现严格警告,因为在 foreach 循环中的赋值中使用了引用,即更改 @ 987654328@转$ret[$key] = array_intersect_assoc_recursive($arr1[$key], $arr2[$key]);
  • $ret[$key] =& array_intersect_assoc_recursive... 导致警告 Only variables should be assigned by reference...。可以用什么来代替 & 号?
  • @KolaB 你的决定是错误的,因为函数的响应只会记录布尔比较值,而不是实际的数组值。看我对这个问题的回答stackoverflow.com/questions/4627076/…
【解决方案2】:
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;
}

【讨论】:

  • 附上你的答案的解释会很棒。
【解决方案3】:

满足您需要的功能:

/**
 * 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-16
    • 2011-11-21
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多