【问题标题】:PHP - Unexpected array_merge_recursive() outputPHP - 意外的 array_merge_recursive() 输出
【发布时间】:2013-06-24 05:49:22
【问题描述】:

我有这个代码

$a1 = array(
    'success'    => TRUE,
    'data'       => array(
        'foo' =>
        array(
            21 =>
            array(
                1 =>
                array(1, 2, 3, 4, 5)
            )
        )
    )
);

$a2 = array(
    'success'    => TRUE,
    'data'       => array(
        'foo' =>
        array(
            21 =>
            array(
                7 =>
                array(6, 7, 8, 9, 10)
            )
        )
    )
);

$results = array();
$results = array_merge_recursive($results, $a1['data']);
$results = array_merge_recursive($results, $a2['data']);
var_dump($results);

根据我对 array_merge_recursive() 的理解,我期望结果是

array
  'foo' => 
    array
      21 => 
        array
          1 => 
            array
              0 => int 1
              1 => int 2
              2 => int 3
              3 => int 4
              4 => int 5
           7 =>
              0 => int 6
              1 => int 7
              2 => int 8
              3 => int 9
              4 => int 10

相反,我得到了这个

array
  'foo' => 
    array
      21 => 
        array
          1 => 
            array
              0 => int 1
              1 => int 2
              2 => int 3
              3 => int 4
              4 => int 5
      22 => 
        array
          7 => 
            array
              0 => int 6
              1 => int 7
              2 => int 8
              3 => int 9
              4 => int 10

22 索引从何而来?为什么输出不一样?我是不是用错了函数?

【问题讨论】:

    标签: php array-merge


    【解决方案1】:

    array_merge_recursive 合并与第一个数组相同深度的元素/数组,但如果两个数组的键都是数字索引并且它们相同,则将其附加到它。这就是你的情况。从那时起,您的数组将附加在第二级,其中通过创建索引22 找到索引21。要接收所需的输出,您必须将索引 21 更改为字符串键,例如 "x21"

    php 手册中的注释

    如果输入数组具有相同的字符串键,则 这些键被合并到一个数组中,这就完成了 递归地,因此如果其中一个值是数组本身,则 函数会将其与另一个数组中的相应条目合并 也。但是,如果数组具有相同的数字键,则后面的 value 不会覆盖原始值,而是会被追加。

    【讨论】:

      【解决方案2】:

      我刚遇到同样的问题,我想合并数组,但意外地发现结果中的键自动更改了。原因是我的“键”是十进制数字字符串,没有任何字母字符。

      但幸运的是,我注意到如果键有字母字符,它们可以被保留。于是就想出了下面的思路,就是在合并之前递归的给每个key附加一个字母'S',然后在最终的结果中去掉。

      详情请参考enhanced_array_merge_recursive函数:

      <?php
      
      $aa = [
        '10' => 'book',
        '14' => ['cat'],
      ];
      
      $ab = [
        '12' => 'cd',
        '18' => 'cup',
        '14' => ['dog'],
      ];
      
      var_dump(enhanced_array_merge_recursive($aa, $ab));
      
      function revise_keys($source)
      {
          if (!is_array($source)) {
              return $source;
          }
      
          $target = [];
      
          foreach ($source as $key => $value) {
              $target['S' . $key] = revise_keys($value);
          }
      
          return $target;
      }
      
      function revert_keys($source)
      {
          if (!is_array($source)) {
              return $source;
          }
      
          $target = [];
      
          foreach ($source as $key => $value) {
              $target[substr($key, 1 - strlen($key))] = revert_keys($value);
          }
      
          return $target;
      }
      
      function enhanced_array_merge_recursive(...$candidates)
      {
          $merged = [];
      
          foreach ($candidates as $candidate) {
              if (!is_array($candidate)) {
                  continue;
              }
      
              $merged = array_merge_recursive($merged, revise_keys($candidate));
          }
      
          return revert_keys($merged);
      }
      

      输出如下所示:

      array(4) {
        [10] =>
        string(4) "book"
        [14] =>
        array(1) {
          [0] =>
          array(2) {
            [0] =>
            string(3) "cat"
            [1] =>
            string(3) "dog"
          }
        }
        [12] =>
        string(2) "cd"
        [18] =>
        string(3) "cup"
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-13
        • 2020-02-21
        • 2012-05-06
        • 2019-03-21
        • 2019-08-29
        相关资源
        最近更新 更多