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

时间:2013-04-24 23:12:49

标签: php arrays multidimensional-array

我正在尝试添加两个多维数组。该函数应该像添加数组一样完全相同:$ 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

目前,似乎如果我添加两个多维数组,覆盖功能似乎只适用于第一个数组维度。这意味着在这种情况下,$ 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'。我不太确定如何解决这个问题。

3 个答案:

答案 0 :(得分:1)

您可以尝试使用 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);
?>

<强>输出: 数组([something] =&gt;数组([0] =&gt; 0 [1] =&gt; 1000)[嵌套] =&gt;数组([a] =&gt;数组([0] =&gt; [1] =&gt; 1)[b] =&gt; [c] =&gt; [new] =&gt; 4))

答案 1 :(得分:1)

递归函数绝对是这里的方法。我刚刚掀起了以下内容。请注意在&的函数声明中使用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数组中的某个键设置为{ {1}}。要更改此行为,请在null的{​​{1}}子句中添加另一个if语句。


使用示例

使用示例数组,输出

else

fill_in_aux

击穿

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

如果参数以print_r(fill_in($user_array, $default_array)); 符号开头,则参数将通过 引用 传递,而不是被复制。当函数对参数进行修改时,它实际上是直接对传入的变量进行更改。

有关详细信息,请查看:http://php.net/manual/en/language.references.pass.php

答案 2 :(得分:0)

令人惊讶的是,七年前没有人为您提供本机功能array_replace_recursive()。 @bestprogrammerintheworld处在正确的轨道上,但选择了错误的递归调用。

使用此功能以外的任何其他功能都将不必要的代码膨胀,并且很可能会降低性能。

代码:(Demo

var_export(
    array_replace_recursive($default, $user)
);

输出:

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