最有效的数学方法将两个多维数组相加?

3

考虑两个简单的数组:

<?php
  $array1 = array(
    'blue' => 5,

    'green' => array(
      'square' => 10,
      'sphere' => 0.5,
      'triangle' => 3
    ),

    'red' => array(
      'circle' => 1000,
    ),

    'black' => 4,

  );

  $array2 = array(
    'blue' => 1,

    'green' => array(
       'square' => 11,
       'circle' => 5,
    ),

    'purple' => 10,

    'yellow' => array(
      'triangle' => 4
    ),

    'black' => array(
      'circle' => 6,
    ),

  );

我需要以递归方式将每个数组$array1$array2的值相加,并保留键。
  • 保留键
  • 如果一个键在$array1中不存在但存在于$array2中,则最终数组仅包含$array2的值(反之亦然)
  • 如果两个数组中都存在,则数字值将被相加+
  • 非数字值不会被修改
  • 如果$array1中的值指向另一个子数组,在$array2中它指向一个值,那么该键的结束值将包含一个子数组,其中包含来自$array1的值以及使用父名称及其值的新键/值(请参阅示例中的black
  • 应能够在几乎无限的嵌套中工作

为了澄清,例如我们说

<?php 
  $final = array_merge_special($array1, $array2);

  // We would end up with, if you var_export()'d final, something like:
  // (Note: Hope I didn't make mistakes in this or it will be confusing,
  // so expect mild human error)

  $final = array(
    'blue' => 6, // 5+1

    'green' => array(
      'square' => 21, // (10+11)
      'sphere' => 0.5, // only in $array1
      'triangle' => 3 // only in $array1
      'circle' => 5, // only in $array2
    ),

    'purple' => 10, // only in $array2

    'yellow' => array( // only in $array2
      'triangle' => 4
    ),

    'red' => array( // only in $array1
      'circle' => 1000,
    ),

    'black' => array(
      'circle' => 6, // untouched, while $black is present in both, the $array1 value does not have a 'circle' key, and is actually only a key/value (see below)
      'black' => 4, // the key/value from $array1 that was not a subarray, even though it was a subarray in $array2
    ),

  );

对我来说,这似乎非常令人生畏。 我知道我可以循环遍历一个数组并轻松地递归添加值,而且我已经做到了(有点),但是当涉及到特殊规则时(例如black的规则),我甚至无法想象代码会有多糟糕。 必须有一种方法可以在单独循环遍历每个数组并使用unset()合并值的情况下完成此操作。


1
嗨,nezZario。我的第一个答案是错误的,所以我更新了一个可行的解决方案。祝你使用愉快。 - Captain Payalytic
我在这里真的在思考,但如果您将两个数组都转化为具有类似"红色-圆形"键的简单关联数组,进行操作,然后再解开数组,会怎么样? - James C
为什么要这样做呢?我的递归解决方案可行啊。 - Captain Payalytic
1个回答

1
你可以使用array_walk_recursive(请参见:此处查看php手册),可能还需要使用array_merge_recursive。我需要进一步思考才能得到完整的图片。
好的,我决定这行不通!Array_walk_recursive不会将包含数组的键传递给函数。这个问题一直在我的脑海中流转,所以我不得不写一个函数来解决它!下面是函数代码:
function dosum($arin) {
  $arout = array();
  foreach ($arin as $key1 => $item1) {
    $total = 0;
    if(is_array($item1)) {
      foreach($item1 as $key2 => $item2) {
        if(is_numeric($key2))
          $total += $item2;
        else
          if(is_array($item2))
            $arout[$key1] = dosum(array($key2 => $item2));
          else
            $arout[$key1][$key2] =$item2;
      }
      if($total)
        if(isset($arout[$key1]))
          $arout[$key1][$key1] = $total;
        else
          $arout[$key1] = $total;
      }
    else
      $arout[$key1] = $item1;    
    }
  return $arout;
  }

对于给出的 2 个数组,您可以按照以下方式使用它们:
print_r(dosum(array_merge_recursive($array1, $array2)));

array_walk_recursive似乎是一个很好的起点。我建议您首先创建“目标结构” - 即具有您期望在最终结果中的所有元素的总和;然后遍历这些元素,如果两个数组中出现相同的元素,则将它们相加,否则将其赋值为存在的结构中的值。 - Floris

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