PHP:多维数组递归合并

13

我需要合并这两个数组:

$ar1 = array("color" => array("red", "green"), "aa");
$ar2 = array("color" => array( "green", "blue"), "bb");
$result = array_merge_recursive($ar1, $ar2);

期望输出:

[
    'color' => [
        (int) 0 => 'red',
        (int) 1 => 'green',
        (int) 3 => 'blue'
    ],
    (int) 0 => 'aa',
    (int) 1 => 'bb'
]

但是它输出:

[
    'color' => [
        (int) 0 => 'red',
        (int) 1 => 'green',
        (int) 2 => 'green', (!)
        (int) 3 => 'blue'
    ],
    (int) 0 => 'aa',
    (int) 1 => 'bb'
]

我正在寻找最简单的方法来做到这一点,我的数组输入不会比这些示例更深。


2
http://php.net/manual/en/function.array-merge-recursive.php 的第一条评论 - Mark.Ablov
已经测试过了,但是它不起作用。它输出:['color' => [ 'geen', 'blue'], 'bb'] - hjrshng
该手册解释了,参见“描述”,它只会合并“字符串”键,“数字”键将被追加。遗憾的是,这阻止了“array_merge_recursive”函数在不修改“键”的情况下完成您所需的操作。我可以建议您使用“命名”键,这样您的代码会更可靠。 - Ryan Vincent
我不能这样做,因为它是一个庞大的配置文件的一部分,所以我必须对数据进行分组。 - hjrshng
2个回答

36
这里它是。
function array_merge_recursive_ex(array $array1, array $array2)
{
    $merged = $array1;

    foreach ($array2 as $key => & $value) {
        if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
            $merged[$key] = array_merge_recursive_ex($merged[$key], $value);
        } else if (is_numeric($key)) {
             if (!in_array($value, $merged)) {
                $merged[] = $value;
             }
        } else {
            $merged[$key] = $value;
        }
    }

    return $merged;
}

2
另一个很好的例子,类似于这个 - 来自Drupal:https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal_array_merge_deep/7 - Meglio
4
实际上,在这里你不需要通过引用传递任何内容。 - Sergey Onishchenko
我会将 if (is_numeric($key)) 放在最前面,这样数字数组就会被合并而不是被覆盖。 - orenk86
如果您想保留数字键,我建议您将 $merged[] = $value; 更改为 $merged[$key] = $value;。如果不进行此更改,则会忽略数字键值。 - lookbadgers

5

感谢Meglio的评论,您可以将这些函数用于任意数量的数组:

功能

function drupal_array_merge_deep() {
  $args = func_get_args();
  return drupal_array_merge_deep_array($args);
}

// source : https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/drupal_array_merge_deep_array/7.x
function drupal_array_merge_deep_array($arrays) {
    $result = array();
    foreach ($arrays as $array) {
        foreach ($array as $key => $value) {
            // Renumber integer keys as array_merge_recursive() does. Note that PHP
            // automatically converts array keys that are integer strings (e.g., '1')
            // to integers.
            if (is_integer($key)) {
                $result[] = $value;
            }
            elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
                $result[$key] = drupal_array_merge_deep_array(array(
                    $result[$key],
                    $value,
                ));
            }
            else {
                $result[$key] = $value;
            }
        }
    }
    return $result;
}

使用方法

$merged = drupal_array_merge_deep($ar_1, $ar_2);

var_dump($merged);

$merged = drupal_array_merge_deep_array([$ar_1, $ar_2]);

var_dump($merged);

用法(测试数据)

$ar_1 = [
    "item1" => false,
    "item2" => true,
    "item_list" => [
        "sub_item1" => 5,
        "sub_itemlist" => [
            "sub_sub_item1" => 27,
        ],
    ]
];

$ar_2 = [
    "item_list" => [
        "sub_item2" => 5,
        "sub_itemlist" => [
            "sub_sub_item2" => 27,
        ],
    ],
    "item3" => true,
];

使用输出(两个函数相同)

array (size=4)
  'item1' => boolean false
  'item2' => boolean true
  'item_list' => 
    array (size=3)
      'sub_item1' => int 5
      'sub_itemlist' => 
        array (size=2)
          'sub_sub_item1' => int 27
          'sub_sub_item2' => int 27
      'sub_item2' => int 5
  'item3' => boolean true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接