如何合并两个多维数组而不覆盖PHP中的现有键



我试图添加两个多维数组。该函数应该与将数组相加完全相同,如下所示:$new_array = $array1 + $array2,除了它应该与多维数组一起工作。这意味着$array2不应该覆盖现有的键值。

示例:假设我有以下$default_array:

array
  'something' => int 0
  'nested' => 
    array (size=3)
      'a' => null
      'b' => null
      'c' => null

和下面的$user_array:

array
  'something' => int 1000
  'nested' => 
    array (size=3)
      'a' => 1
  'new' => int 4

将两者加在一起(如$user_array + $default_array)应该得到:

array (size=4)
      'something' => int 1000
      'nested' => 
        array (size=3)
          'a' => 1
          'b' => null
          'c' => null
      'new' => int 4

目前,如果我添加两个多维数组,覆盖功能似乎只适用于第一个数组维度。这意味着在这种情况下,'nested'已经存在于$user_array中,所以它不会附加其他值。

编辑:我还应该提到,这需要无限量的维度。

编辑2:我只是试着应用Rain的答案,它没有按预期工作。首先,我收到了"未定义索引"通知。其次,输出不是我想要的。考虑以下数组:

        $default = array(
            'a' => array(
                'a' => 'a',
                'b' => 'b',
                'c' => 'c',
                ),
            );
        $user = array(
            'b' => 1,
            'a' => array(
                'b' => 'something',
                'c' => 'something else',
                'd' => 'd',
                ),
            'c' => 2);

我用Rain函数得到的输出是这样的:

array (size=3)
  'a' => 
    array (size=3)
      'a' => string 'a' (length=1)
      'b' => string 'b' (length=1)
      'c' => string 'c' (length=1)
  'b' => int 1
  'c' => int 2

在这个例子中,子数组中的'b'和'c'键应该分别是'something'和'something else'。我不太确定如何解决这个问题

您可以尝试使用 array_merge_recursive() (不仅仅是array_merge())http://www.php.net/manual/en/function.array-merge-recursive.php

<?php
$defaultarray = array(
'something' => 0,
  'nested' => 
    array (
      'a' => null,
      'b' => null,
      'c' => null));
$newArray = array(
  'something' => 1000, 
  'nested' => 
    array ('a' => 1,
  'new' => 4));
$mergedArray = array_merge_recursive($defaultarray, $newArray);
echo print_r($mergedArray,true);
?>
输出:

数组([一些]=>数组([0]=> 0[1]=> 1000)(嵌套的)=>数组([a] =>数组([0]=> [1]=> 1)[b] => [c] =>[新]=> 4))

递归函数在这里绝对是可行的。我刚刚做了下面这些。注意在fill_in_aux的函数声明中使用了&。这导致第二个参数(称为$default)通过引用传递,而不是通过值传递。它被包装在fill_in中,因此真正的"默认"数组不会被修改。

function fill_in($user, $default) {
    fill_in_aux($user, $default);
    return $default;
}
function fill_in_aux($user, &$default) {
    foreach ($user as $key => $value) {
        if (is_array($value)) {
            fill_in_aux($user[$key], $default[$key]);
        } else {
            $default[$key] = $value;
        }
    }
}

这假设在$default数组中设置的任何内容都应该被$user数组中存在的任何内容覆盖,即使$user数组中的一个键被设置为null。要更改此行为,请在fill_in_auxelse子句中添加另一个if语句。


对于您的示例数组, 的输出
print_r(fill_in($user_array, $default_array));

Array
(
    [something] => 1000
    [nested] => Array
        (
            [a] => 1
            [b] =>
            [c] =>
        )
    [new] => 4
)

分解

通常,在PHP中调用函数时,参数是通过value传递的:函数获取传入变量的副本。这意味着函数可以对参数做任何它想做的事情,但是当函数返回时,传递的原始变量不受影响。

当参数以&符号开头时,参数通过引用传递,而不是被复制。当函数对形参进行修改时,实际上是直接对传入的变量进行修改。

更多信息,请查看:http://php.net/manual/en/language.references.pass.php

我很惊讶七年前没有人提供原生函数array_replace_recursive()。@bestprogrammerintheworld在正确的轨道上,但是选择了错误的递归调用。

使用此函数以外的任何函数都将导致不必要的代码膨胀,并且很可能导致性能下降。

代码(演示):

var_export(
    array_replace_recursive($default, $user)
);
输出:

array (
  'a' => 
  array (
    'a' => 'a',
    'b' => 'something',
    'c' => 'something else',
    'd' => 'd',
  ),
  'b' => 1,
  'c' => 2,
)

相关内容

  • 没有找到相关文章

最新更新