【问题标题】:How to Flatten a Multidimensional Array?如何展平多维数组?
【发布时间】:2010-11-22 03:18:33
【问题描述】:

在 PHP 中是否可以在不使用递归或引用的情况下展平(双/多)维数组?

我只对值感兴趣,因此可以忽略键,我正在考虑 array_map()array_values() 的行。

【问题讨论】:

  • 为什么要避免递归?
  • 你不能在没有递归的情况下对任意深度数组的所有元素做任何事情(你可以把它伪装成迭代,但是土豆,potahto。)如果你只是想避免自己编写递归处理代码, 使用 dk2.php.net/manual/en/function.array-walk-recursive.php 和回调,将元素添加到可用数组中(使用全局、userdata 参数,将其全部放在一个类中并引用 $this 等)
  • @JorenB:我希望看到可以存档的实现。
  • 看看来自Nsplflatten 函数。您也可以使用它指定深度。

标签: php arrays multidimensional-array flatten


【解决方案1】:

从 PHP v7.4 开始,您可以使用扩展运算符并合并数组。简单有效。

$flatArr = array_merge(...$originalArray);

【讨论】:

    【解决方案2】:

    如果你想保留中间键:

    function flattenArray(array &$result, $value, string $key = "")
    {
        if (!is_array($value)) {
            $result[$key] = $value;
            return $result;
        }
        foreach ($value as $subKey => $subArray) {
            $newKey = $key !== "" ? $key . "_" . $subKey : $subKey;
            flattenArray($result, $subArray, $newKey);
        }
        return $result;
    }
    
    $nestedArray = [
        "name" => "John",
        "pets" => [
            ["id" => 1, "name" => "snooop"],
            ["id" => 2, "name" => "medor"],
        ],
        "job" => ["title" => "developper"],
    ];
    
    $intermediateResult = [];
    $flattened = flattenArray($intermediateResult, $nestedArray);
    var_dump($flattened);
    

    这将输出:

    array(6) {
    ["name"]=>
      string(4) "John"
            ["pets_0_id"]=>
      int(1)
      ["pets_0_name"]=>
      string(6) "snooop"
            ["pets_1_id"]=>
      int(2)
      ["pets_1_name"]=>
      string(5) "medor"
            ["job_title"]=>
      string(10) "developper"
    }
    

    https://ideone.com/KXLtzZ#stdout

    【讨论】:

      【解决方案3】:

      任何正在寻找真正干净的解决方案的人;这是一个选项:

      获取具有各种键值配置的数组:

      $test_array = array(
          array('test' => 0, 0, 0, 0),
          array(0, 0, 'merp' => array('herp' => 'derp'), 0),
          array(0, 0, 0, 0),
          array(0, 0, 0, 0)
      );
      $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($test_array));
      var_dump( iterator_to_array($it, false) ) ; 
      

      这将只取每个数组中的值并返回一个平面数组。

      结果中的值输出:

      0 0 0 0 0 0 derp 0 0 0 0 0 0 0 0 0
      

      【讨论】:

      • 我没有投反对票,但我可以想象可能被认为对答案没有帮助的原因是,这类似于 2009 年接受的答案帖子,至少表明相同。请比较您自己的并发表评论。
      【解决方案4】:

      扁平化数组的 Laravel 助手是 Arr::flatten()

      【讨论】:

      • 从来没有注意 flatten() 可以做多维数组。很高兴知道 Laravel 很棒!
      【解决方案5】:

      在 PHP 5.6 及更高版本中,您可以在使用 ... 运算符解包外部数组后使用 array_merge 展平二维数组。代码简洁明了。

      array_merge(...$a);
      

      这也适用于关联数组的集合。

      $a = [[10, 20], [30, 40]];
      $b = [["x" => "X", "y" => "Y"], ["p" => "P", "q" => "Q"]];
      
      print_r(array_merge(...$a));
      print_r(array_merge(...$b));
      
      Array
      (
          [0] => 10
          [1] => 20
          [2] => 30
          [3] => 40
      )
      Array
      (
          [x] => X
          [y] => Y
          [p] => P
          [q] => Q
      )
      

      在 PHP 8.0 及更低版本中,当外部数组有非数字键时,数组解包不起作用。从 PHP 8.1 开始支持 unpacking array with string keys。要支持 8.0 及以下版本,请先致电array_values

      $c = ["a" => ["x" => "X", "y" => "Y"], "b" => ["p" => "P", "q" => "Q"]];
      print_r(array_merge(...array_values($c)));
      
      Array
      (
          [x] => X
          [y] => Y
          [p] => P
          [q] => Q
      )
      

      更新:基于@MohamedGharib 的评论

      如果外部数组为空,这将引发错误,因为 array_merge 将使用零参数调用。可以通过添加一个空数组作为第一个参数来避免。

      array_merge([], ...$a);
      

      【讨论】:

      • 这仅在数组的每个元素都是数组时才有效。如果数组包含混合类型,例如标量,则会发生错误。
      • @Otheus 那是因为上面的解决方案没有使用递归。正如你所说,它需要一个数组数组。但从好的方面来说,这应该比其他方法快得多,因为它没有函数调用的额外开销。
      • 如果外部数组为空会抛出错误,如果与空数组结合可以避免array_merge([], ...$a);
      • 哇,这是一些很酷的古怪语法。5 年的 PHP 编程,从未听说过这个 (...) 运算符。虽然像魅力一样工作!
      • 非常酷。不适用于 100% 的情况,但在它起作用时是完美的。 $a = array_merge( array(), ...array_values( $a ) ); 为我工作,用$wpdb->get_results( $sql, ARRAY_N ) 扁平化查询结果是wordpress 中的单列
      【解决方案6】:

      如果您还想保留您的钥匙,那就是解决方案。

      function flatten(array $array) {
          $return = array();
          array_walk_recursive($array, function($value, $key) use (&$return) { $return[$key] = $value; });
          return $return;
      }
      

      不幸的是,它只输出最终的嵌套数组,没有中间键。所以对于下面的例子:

      $array = array(
          'sweet' => array(
              'a' => 'apple',
              'b' => 'banana'),
          'sour' => 'lemon'); 
      print_r(flatten($fruits));
      

      输出是:

      Array
      (
          [a] => apple
          [b] => banana
          [sour] => lemon
      )
      

      【讨论】:

      • 这正是我想要的。我将函数名称更改为flatten() 以匹配第二个示例。
      • 是否有可能得到类似的回报:Array ([sweet__a] => apple [sweet__b] =>banana [sour] => lemon)
      【解决方案7】:

      要扁平化无递归(如您所要求的),您可以使用stack。当然,您可以将其放入它自己的函数中,例如array_flatten。以下是无键工作的版本:。

      function array_flatten(array $array)
      {
          $flat = array(); // initialize return array
          $stack = array_values($array); // initialize stack
          while($stack) // process stack until done
          {
              $value = array_shift($stack);
              if (is_array($value)) // a value to further process
              {
                  array_unshift($stack, ...$value);
              }
              else // a value to take
              {
                  $flat[] = $value;
              }
          }
          return $flat;
      }
      

      元素按它们的顺序处理。因为子元素会被移到栈顶,所以接下来会处理它们。

      也可以考虑密钥,但是,您需要不同的策略来处理堆栈。这是必需的,因为您需要处理子数组中可能存在的重复键。相关问题中的类似答案:PHP Walk through multidimensional array while preserving keys

      我不确定,但我过去曾对此进行过测试:RecurisiveIterator 确实使用递归,所以这取决于您真正需要什么。应该也可以创建基于堆栈的递归迭代器:

      foreach(new FlatRecursiveArrayIterator($array) as $key => $value)
      {
          echo "** ($key) $value\n";
      }
      

      Demo

      到目前为止,我还没有实现基于RecursiveIterator 的堆栈,我认为这是个好主意。

      【讨论】:

      • +1 表示出色的 array_flatten 函数。我必须在 else 语句中添加 if(!empty($value)){$flat[] = $value} 以防止将空添加到结果数组中。很棒的功能!
      • 展平操作可以从$stack = array_merge(array_values($value), $stack); 减少到array_unshift($stack, ...$value); 并且array_values() 调用对于大多数人来说可能是无关紧要的,但是考虑到它早于v5,编辑答案似乎并不正确。 6.
      • @Walf:是的,这是唯一的原因。感谢您的提示,我已经编辑了它。
      【解决方案8】:

      这可以通过使用array_walk_recursive来实现

      $a = array(1,2,array(3,4, array(5,6,7), 8), 9);
      array_walk_recursive($a, function($v) use (&$r){$r[]=$v;});
      print_r($r);
      

      工作示例:- https://3v4l.org/FpIrG

      【讨论】:

        【解决方案9】:

        使用递归生成器怎么样? https://ideone.com/d0TXCg

        <?php
        
        $array = [
            'name' => 'Allen Linatoc',
            'profile' => [
                'age' => 21,
                'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
            ]
        ];
        
        foreach (iterate($array) as $item) {
            var_dump($item);
        };
        
        function iterate($array)
        {
            foreach ($array as $item) {
                if (is_array($item)) {
                    yield from iterate($item);
                } else {
                    yield $item;
                }
            }
        }
        

        【讨论】:

          【解决方案10】:

          如果你真的不喜欢递归......请尝试换档:)

          $a = array(1,2,array(3,4, array(5,6,7), 8), 9);
          $o = [];
          for ($i=0; $i<count($a); $i++) {
              if (is_array($a[$i])) {
                  array_splice($a, $i+1, 0, $a[$i]);
              } else {
                  $o[] = $a[$i];
              }
          }
          

          注意:在这个简单的版本中,它不支持数组键。

          【讨论】:

          • 这是一个有趣的方法。与其他解决方案相比,它编辑原始数组 ($a)。如果你用continue 替换它,它会更快一些。
          【解决方案11】:

          这是一个简单的方法:

          $My_Array = array(1,2,array(3,4, array(5,6,7), 8), 9);
          
          function checkArray($value) {
              foreach ($value as $var) {
                  if ( is_array($var) ) {
                      checkArray($var);
                  } else {
                      echo $var;
                  }
              }
          }
          
          checkArray($My_Array);
          

          【讨论】:

            【解决方案12】:

            我相信这是最干净的解决方案,无需使用任何突变或不熟悉的类。

            <?php
            
            function flatten($array)
            {
                return array_reduce($array, function($acc, $item){
                    return array_merge($acc, is_array($item) ? flatten($item) : [$item]);
                }, []);
            }
            
            
            // usage
            $array = [1, 2, [3, 4], [5, [6, 7]], 8, 9, 10];
            print_r(flatten($array));
            

            【讨论】:

              【解决方案13】:
              <?php
              //recursive solution
              
              //test array
              $nested_array = [[1,2,[3]],4,[5],[[[6,[7=>[7,8,9,10]]]]]];
              
              /*-----------------------------------------
              function call and return result to an array
              ------------------------------------------*/
              $index_count = 1;
              $flatered_array = array();
              $flatered_array = flat_array($nested_array, $index_count);
              
              /*-----------------------------------------
              Print Result
              -----------------------------------------*/
              echo "<pre>";
              print_r($flatered_array);
              
              
              /*-----------------------------------------
              function to flaten an array 
              -----------------------------------------*/
              function flat_array($nested_array, & $index_count, & $flatered_array) {
              
                foreach($nested_array AS $key=>$val) {
                    if(is_array($val)) {
                      flat_array($val, $index_count, $flatered_array);
                    }
                    else {
                      $flatered_array[$index_count] = $val;
                      ++$index_count;
                    }      
                }
              
              return $flatered_array;
              }
              ?>
              

              【讨论】:

                【解决方案14】:

                直截了当单线回答。

                function flatten_array(array $array)
                {
                    return iterator_to_array(
                         new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array)));
                }
                

                用法:

                $array = [
                    'name' => 'Allen Linatoc',
                    'profile' => [
                        'age' => 21,
                        'favourite_games' => [ 'Call of Duty', 'Titanfall', 'Far Cry' ]
                    ]
                ];
                
                print_r( flatten_array($array) );
                

                输出(在 PsySH 中):

                Array
                (
                    [name] => Allen Linatoc
                    [age] => 21
                    [0] => Call of Duty
                    [1] => Titanfall
                    [2] => Far Cry
                )
                

                现在如何处理密钥完全取决于您。干杯


                编辑(2017-03-01)

                引用Nigel Alderton的关注/问题:

                澄清一下,这会保留键(甚至是数字键),因此具有相同键的值会丢失。例如,$array = ['a',['b','c']] 变为 Array ([0] =&gt; b, [1] =&gt; c )'a' 丢失了,因为 'b' 也有一个 0

                引用Svish的回答:

                只需将 false 作为第二个参数 ($use_keys) 添加到 iterator_to_array 调用

                【讨论】:

                • 澄清一下,这会保留键(甚至是数字键),因此具有相同键的值会丢失。例如,$array = ['a',['b','c']] 变为 Array ([0] =&gt; b, [1] =&gt; c )'a' 丢失了,因为 'b' 也有一个 0 键。
                • @NigelAlderton 只需将 false 作为第二个参数 ($use_keys) 添加到 iterator_to_array 调用。
                • 使用iterator_to_array($it, false);时要小心!如果此参数未设置或设置为 TRUE,重复键将被覆盖!!!如果您将它与 array(1,2,array(3,4, array(5,6,7), 8), 9); 一起使用,这将返回 5 6 7 9 而不是 1 2 3 4 5 6 7 8 9 预期。
                【解决方案15】:

                您可以使用ouzo goodies

                 $result = Arrays::flatten($multidimensional);
                

                见:Here

                【讨论】:

                  【解决方案16】:

                  仅展平二维数组:

                  $arr = [1, 2, [3, 4]];
                  $arr = array_reduce($arr, function ($a, $b) {
                       return array_merge($a, (array) $b);
                  }, []);
                  
                  // Result: [1, 2, 3, 4]
                  

                  【讨论】:

                    【解决方案17】:

                    试试下面这个简单的函数:

                    function _flatten_array($arr) {
                      while ($arr) {
                        list($key, $value) = each($arr); 
                        is_array($value) ? $arr = $value : $out[$key] = $value;
                        unset($arr[$key]);
                      }
                      return (array)$out;
                    }
                    

                    所以从这里:

                    array (
                      'und' => 
                      array (
                        'profiles' => 
                        array (
                          0 => 
                          array (
                            'commerce_customer_address' => 
                            array (
                              'und' => 
                              array (
                                0 => 
                                array (
                                  'first_name' => 'First name',
                                  'last_name' => 'Last name',
                                  'thoroughfare' => 'Address 1',
                                  'premise' => 'Address 2',
                                  'locality' => 'Town/City',
                                  'administrative_area' => 'County',
                                  'postal_code' => 'Postcode',
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    )
                    

                    你得到:

                    array (
                      'first_name' => 'First name',
                      'last_name' => 'Last name',
                      'thoroughfare' => 'Address 1',
                      'premise' => 'Address 2',
                      'locality' => 'Town/City',
                      'administrative_area' => 'County',
                      'postal_code' => 'Postcode',
                    )
                    

                    【讨论】:

                    • 也许你应该检查你的功能......似乎没有像预期的那样工作
                    • @Emiliano 尝试提出一个新问题,也许您的输入数据不同,所以它不适用于您的特定情况。
                    • 我们很少有问题,每个都是不推荐使用的函数,您可以改进这一点,您不是这里的新手,如果您的代码与特定版本的 php 一起工作,您应该知道第二个说第三个如果不能处理所有数据,请说出来
                    【解决方案18】:

                    因为here 中的代码看起来很吓人。这是一个函数,它也可以将多维数组转换为与 html 格式兼容的语法,但更容易阅读。

                    /**
                     * Flattens a multi demensional array into a one dimensional
                     * to be compatible with hidden html fields.
                     *
                     * @param array $array
                     *  Array in the form:
                     *  array(
                     *    'a' => array(
                     *      'b' => '1'
                     *    )
                     *  )
                     *
                     * @return array
                     *  Array in the form:
                     *  array(
                     *    'a[b]' => 1,
                     *  )
                     */
                    function flatten_array($array) {
                      // Continue until $array is a one-dimensional array.
                      $continue = TRUE;
                      while ($continue) {
                        $continue = FALSE;
                    
                        // Walk through top and second level of $array and move 
                        // all values in the second level up one level.
                        foreach ($array as $key => $value) {
                          if (is_array($value)) {
                            // Second level found, therefore continue.
                            $continue = TRUE;
                    
                            // Move each value a level up.
                            foreach ($value as $child_key => $child_value) {
                              $array[$key . '[' . $child_key . ']'] = $child_value;
                            }
                    
                            // Remove second level array from top level.
                            unset($array[$key]);
                          }
                        }
                      }
                    
                      return $array;
                    }
                    

                    【讨论】:

                      【解决方案19】:

                      这是我的解决方案,使用参考:

                      function arrayFlatten($array_in, &$array_out){
                      
                          if(is_array($array_in)){
                              foreach ($array_in as $element){
                                     arrayFlatten($element, $array_out);
                              }
                          }
                          else{
                              $array_out[] = $array_in; 
                          }
                      }
                      
                      $arr1 = array('1', '2', array(array(array('3'), '4', '5')), array(array('6')));
                      
                      arrayFlatten($arr1, $arr2);
                      
                      echo "<pre>";
                      print_r($arr2);
                      echo "</pre>";
                      

                      【讨论】:

                      • 请解释一下您的 sn-p 是如何工作的以及为什么它是一个好主意。仅代码的答案在 StackOverflow 上的价值很低,因为它们在教育/授权 OP 和未来的研究人员方面做得很差。请记住,我们永远不会只与 OP 交谈。旧页面用于关闭新页面,因此页面需要提供足够的信息以解决未来提问者的问题。
                      【解决方案20】:

                      二维数组的解决方案

                      请试试这个:

                      $array  = your array
                      
                      $result = call_user_func_array('array_merge', $array);
                      
                      echo "<pre>";
                      print_r($result);
                      

                      编辑:13 年 8 月 21 日

                      这是适用于多维数组的解决方案:

                      function array_flatten($array) {
                          $return = array();
                          foreach ($array as $key => $value) {
                              if (is_array($value)){
                                  $return = array_merge($return, array_flatten($value));
                              } else {
                                  $return[$key] = $value;
                              }
                          }
                      
                          return $return;
                      }
                      
                      $array  = Your array
                      
                      $result = array_flatten($array);
                      
                      echo "<pre>";
                      print_r($result);
                      

                      参考:http://php.net/manual/en/function.call-user-func-array.php

                      【讨论】:

                      • 谢谢,第一个解决方案在我从 PDO 获得的阵列上工作,而其他解决方案没有。
                      • 这是一个糟糕的策略。 call_user_func_array('array_merge', [])(注意空数组)返回 null 并触发 php 警告错误。如果您知道您的数组不会为空,这是一个巧妙的解决方案,但这不是许多人可以做出的常见假设。
                      • OP 专门要求提供非递归解决方案。
                      • 哇,很酷的二维平面!但为了防止通知,只需使用$result = $array ?call_user_func_array('array_merge', $array) : [];
                      • 很酷,但你不是碰巧有一个反函数 array-deflatten 吗?
                      【解决方案21】:

                      如果你有一个对象数组并且想用一个节点将它展平,只需使用这个函数:

                      function objectArray_flatten($array,$childField) {
                          $result = array();
                          foreach ($array as $node)
                          {
                              $result[] = $node;
                              if(isset($node->$childField))
                              {
                                  $result = array_merge(
                                      $result, 
                                      objectArray_flatten($node->$childField,$childField)
                                  );
                                  unset($node->$childField);
                              }
                      
                          }
                          return $result;
                      }
                      

                      【讨论】:

                        【解决方案22】:

                        我需要以 HTML 输入格式表示 PHP 多维数组。

                        $test = [
                            'a' => [
                                'b' => [
                                    'c' => ['a', 'b']
                                ]
                            ],
                            'b' => 'c',
                            'c' => [
                                'd' => 'e'
                            ]
                        ];
                        
                        $flatten = function ($input, $parent = []) use (&$flatten) {
                            $return = [];
                        
                            foreach ($input as $k => $v) {
                                if (is_array($v)) {
                                    $return = array_merge($return, $flatten($v, array_merge($parent, [$k])));
                                } else {
                                    if ($parent) {
                                        $key = implode('][', $parent) . '][' . $k . ']';
                        
                                        if (substr_count($key, ']') != substr_count($key, '[')) {
                                            $key = preg_replace('/\]/', '', $key, 1);
                                        }
                                    } else {
                                        $key = $k;
                                    }           
                        
                                    $return[$key] = $v;
                                }
                            }
                        
                            return $return;
                        };
                        
                        die(var_dump( $flatten($test) ));
                        
                        array(4) {
                          ["a[b][c][0]"]=>
                          string(1) "a"
                          ["a[b][c][1]"]=>
                          string(1) "b"
                          ["b"]=>
                          string(1) "c"
                          ["c[d]"]=>
                          string(1) "e"
                        }
                        

                        【讨论】:

                        • @AlixAxel 这个评论有什么关系?发错了..?
                        • 没有。我认为它与您正在做的事情非常相似并决定分享它,我认为唯一的区别是我的表示也是有效的 PHP - 形式为 $var['a']['b']['c'][0] = 'a'; ...
                        • 我故意需要 HTML 输出。虽然谢谢你的分享。
                        • 我觉得这是对错误问题的正确答案。回答时,请尝试按原样回答问题 - 否则页面可能会偏离核心问题并让未来的研究人员感到困惑。
                        【解决方案23】:
                        /**
                         * For merging values of a multidimensional array into one 
                         *
                         * $array = [
                         *     0 => [
                         *         0 => 'a1',
                         *         1 => 'b1',
                         *         2 => 'c1',
                         *         3 => 'd1'
                         *     ],
                         *     1 => [
                         *         0 => 'a2',
                         *         1 => 'b2',
                         *         2 => 'c2',
                         *     ]
                         * ];
                         *
                         * becomes : 
                         *
                         * $array = [
                         *     0 => 'a1',
                         *     1 => 'b1',
                         *     2 => 'c1',
                         *     3 => 'd1',
                         *     4 => 'a2',
                         *     5 => 'b2',
                         *     6 => 'c2',
                         *     
                         * ]
                         */
                        array_reduce
                        (
                            $multiArray
                            , function ($lastItem, $currentItem) {
                                $lastItem = $lastItem ?: array();
                                return array_merge($lastItem, array_values($currentItem));
                            }
                        );
                        

                        Gist snippet

                        【讨论】:

                        • 这个好像只支持二维数组。
                        • 你是对的。没有必要使用它。我认为最好的解决方案是“太多 php”的答案。
                        【解决方案24】:

                        我只是想指出这是一个折叠,所以可以使用 array_reduce:

                        array_reduce($my_array, 'array_merge', array());
                        

                        编辑:请注意,这可以组合成展平任意数量的级别。我们可以通过多种方式做到这一点:

                        // Reduces one level
                        $concat   = function($x) { return array_reduce($x, 'array_merge', array()); };
                        
                        // We can compose $concat with itself $n times, then apply it to $x
                        // This can overflow the stack for large $n
                        $compose  = function($f, $g) {
                            return function($x) use ($f, $g) { return $f($g($x)); };
                        };
                        $identity = function($x) { return $x; };
                        $flattenA = function($n) use ($compose, $identity, $concat) {
                            return  function($x) use ($compose, $identity, $concat, $n) {
                                return ($n === 0)? $x
                                                 : call_user_func(array_reduce(array_fill(0, $n, $concat),
                                                                               $compose,
                                                                               $identity),
                                                                  $x);
                            };
                        };
                        
                        // We can iteratively apply $concat to $x, $n times
                        $uncurriedFlip     = function($f) {
                            return  function($a, $b) use ($f) {
                                return $f($b, $a);
                            };
                        };
                        $iterate  = function($f) use ($uncurriedFlip) {
                            return  function($n) use ($uncurriedFlip, $f) {
                            return  function($x) use ($uncurriedFlip, $f, $n) {
                                return ($n === 0)? $x
                                                 : array_reduce(array_fill(0, $n, $f),
                                                                $uncurriedFlip('call_user_func'),
                                                                $x);
                            }; };
                        };
                        $flattenB = $iterate($concat);
                        
                        // Example usage:
                        $apply    = function($f, $x) {
                            return $f($x);
                        };
                        $curriedFlip = function($f) {
                            return  function($a) use ($f) {
                            return  function($b) use ($f, $a) {
                                return $f($b, $a);
                            }; };
                        };
                        
                        var_dump(
                            array_map(
                                call_user_func($curriedFlip($apply),
                                               array(array(array('A', 'B', 'C'),
                                                           array('D')),
                                                     array(array(),
                                                           array('E')))),
                                array($flattenA(2), $flattenB(2))));
                        

                        当然,我们也可以使用循环,但问题要求使用沿 array_map 或 array_values 行的组合函数。

                        【讨论】:

                        • 多维!= 二维。
                        • @atamur 这适用于 PHP 5.3+。如 array_reduce 的更改日志中所述,$initial 在 5.3 之前只能是整数,然后允许“混合”(即您的归约函数支持的任何内容)
                        • @AlixAxel 你说得对,多维!= 二维,但这可以组合成展平任意数量的级别。组合折叠的一个很好的结果是它遵循一个固定的限制。如果我有一个嵌套到 5 个级别的数组,我可以将其 fold 它分为 4 个级别,或者 fold . fold 它获得 3 个级别,或者 fold . fold . fold 它获得 2 个级别,等等。这也可以防止错误被隐藏;例如。如果我想展平一个 5D 数组但我得到一个 4D 数组,错误将立即触发。
                        • 我喜欢这个解决方案,用于二维数组。完全符合要求。
                        • 我同意你的单层定义是最好的答案,它也非常简洁。但是我认为您错误地将其命名为$concat,我认为您应该将其命名为$flattenarray_merge 是 concat 的 php 等价物。 I triedarray_concat 添加为 array_merge 的别名。
                        【解决方案25】:

                        这个版本可以做深、浅或特定数量的关卡:

                        /**
                         * @param  array|object $array  array of mixed values to flatten
                         * @param  int|boolean  $level  0:deep, 1:shallow, 2:2 levels, 3...
                         * @return array
                         */
                        function flatten($array, $level = 0) {
                            $level = (int) $level;
                            $result = array();
                            foreach ($array as $i => $v) {
                                if (0 <= $level && is_array($v)) {
                                    $v = flatten($v, $level > 1 ? $level - 1 : 0 - $level);
                                    $result = array_merge($result, $v);
                                } elseif (is_int($i)) {
                                    $result[] = $v;
                                } else {
                                    $result[$i] = $v; 
                                }
                            }
                            return $result;
                        }
                        

                        【讨论】:

                        • 除了解释这个 sn-p 可以做什么之外,请向未来的研究人员解释它是如何工作的。
                        【解决方案26】:

                        诀窍是通过引用传递源数组和目标数组。

                        function flatten_array(&$arr, &$dst) {
                            if(!isset($dst) || !is_array($dst)) {
                                $dst = array();
                            }
                            if(!is_array($arr)) {
                                $dst[] = $arr;
                            } else {
                                foreach($arr as &$subject) {
                                    flatten_array($subject, $dst);
                                }
                            }
                        }
                        
                        $recursive = array('1', array('2','3',array('4',array('5','6')),'7',array(array(array('8'),'9'),'10')));
                        echo "Recursive: \r\n";
                        print_r($recursive);
                        $flat = null;
                        flatten_array($recursive, $flat);
                        
                        echo "Flat: \r\n";
                        print_r($flat);
                        
                        // If you change line 3 to $dst[] = &$arr; , you won't waste memory,
                        // since all you're doing is copying references, and imploding the array 
                        // into a string will be both memory efficient and fast:)
                        
                        echo "String:\r\n";
                        echo implode(',',$flat);
                        

                        【讨论】:

                          【解决方案27】:

                          对于 php 5.2

                          function flatten(array $array) {
                              $result = array();
                          
                              if (is_array($array)) {
                                  foreach ($array as $k => $v) {
                                      if (is_array($v)) {
                                          $result = array_merge($result, flatten($v));
                                      } else {
                                          $result[] = $v;
                                      }
                                  }
                              }
                          
                              return $result;
                          }
                          

                          【讨论】:

                          • 请在此纯代码答案中包含一些解释。
                          【解决方案28】:

                          使用递归。希望在看到它有多不复杂后,一旦你看到它有多不复杂,你对递归的恐惧就会消失。

                          function flatten($array) {
                              if (!is_array($array)) {
                                  // nothing to do if it's not an array
                                  return array($array);
                              }
                          
                              $result = array();
                              foreach ($array as $value) {
                                  // explode the sub-array, and add the parts
                                  $result = array_merge($result, flatten($value));
                              }
                          
                              return $result;
                          }
                          
                          
                          $arr = array('foo', array('nobody', 'expects', array('another', 'level'), 'the', 'Spanish', 'Inquisition'), 'bar');
                          echo '<ul>';
                          foreach (flatten($arr) as $value) {
                              echo '<li>', $value, '</li>';
                          }
                          echo '<ul>';
                          

                          输出:

                          <ul><li>foo</li><li>nobody</li><li>expects</li><li>another</li><li>level</li><li>the</li><li>Spanish</li><li>Inquisition</li><li>bar</li><ul>
                          

                          【讨论】:

                          • 我不害怕递归,我只是想学习其他方法来做同样的事情。
                          • 这个递归+1:希望看到它有多不复杂,一旦你看到它有多不复杂,你对递归的恐惧就会消失。
                          • 好的,这已经结束了。 如何回复(“我不害怕递归”)比初始声明(“( ...) 你对递归的恐惧会消散 (...)"),2013 年 2 月 5 日?
                          【解决方案29】:

                          您可以使用Standard PHP Library (SPL) 来“隐藏”递归。

                          $a = array(1,2,array(3,4, array(5,6,7), 8), 9);
                          $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
                          foreach($it as $v) {
                            echo $v, " ";
                          }
                          

                          打印

                          1 2 3 4 5 6 7 8 9 
                          

                          【讨论】:

                          • 我是唯一一个认为“RecursiveIteratorIterator”是一个愚蠢的名字的人吗?
                          • 它比“吸引人”更“合乎逻辑”。不是所有的东西都能有一个很棒的名字,比如 JOGL、Knol 或 Azure :-)
                          • 这不适用于作为子项的空数组。他们将作为父母返回。
                          • iterator_to_array($it, false) 避免了对 foreach 的需要。
                          • 在其他人介绍的基础上,我能够制作这个小助手:function flatten($arr){ $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); return iterator_to_array($it, true); }希望这对其他人有所帮助。
                          【解决方案30】:

                          PHP 5.3 开始,最短的解决方案似乎是 array_walk_recursive() 与新的闭包语法:

                          function flatten(array $array) {
                              $return = array();
                              array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
                              return $return;
                          }
                          

                          【讨论】:

                          • 如果你想要键,function flatten(array $array) { $return = array(); array_walk_recursive($array, function($a,$b) 使用 (&$return) { $return[$b] = $a; });返回 $return; }
                          • 你能重写它以与 php 5.2 一起使用吗?
                          • @Alex 不幸的是,您需要 use 语法才能使其与 array_walk_recursive 一起使用,因为它不会通过引用接受可选的 $userdata 参数
                          • 看起来适用于此类数组 -> ideone.com/DsmApP 但不适用于此类 -> ideone.com/5Kltva 还是我?
                          • @Sebastian Piskorski 这是因为您的值被视为键,所以一旦您在数组中引入自己的键=>值对,您在第一个索引位置的数组值就会被视为键没有值,并且因为键必须是唯一的,当两个键匹配时,您的值将被添加到同一个键中。一个简单的解决方案是先对数组进行排序。这是 PHP 固有的行为。
                          猜你喜欢
                          • 2012-08-27
                          • 2020-06-06
                          • 1970-01-01
                          • 2011-09-05
                          • 1970-01-01
                          • 2013-09-12
                          相关资源
                          最近更新 更多