복붙노트

다차원 배열을 단순화하는 방법?

PHP

다차원 배열을 단순화하는 방법?

재귀 또는 참조를 사용하지 않고 (쌍 / 다중) 차원 배열을 병합하는 것이 PHP에서 가능합니까?

키가 무시 될 수 있도록 값에만 관심이 있습니다. array_map () 및 array_values ​​() 행에서 생각하고 있습니다.

해결법

  1. ==============================

    1.

    표준 PHP 라이브러리 (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 
    
  2. ==============================

    2.

    PHP 5.3에서 가장 짧은 해결책은 새로운 closure 구문을 가진 array_walk_recursive () 인 것 같습니다 :

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

    3.

    2 차원 배열 솔루션

    이것을 시도하십시오 :

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

    편집 : 21-8 월 -13

    다음은 다차원 배열에서 작동하는 솔루션입니다.

    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

  4. ==============================

    4.

    w / o 재귀를 평평하게하려면 (요청한대로) 스택을 사용할 수 있습니다. 당연히 array_flatten과 같은 자신의 함수에 넣을 수 있습니다. 다음은 w / o 키가 작동하는 버전입니다.

    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
            {
                $stack = array_merge(array_values($value), $stack);
            }
            else // a value to take
            {
               $flat[] = $value;
            }
        }
        return $flat;
    }
    

    요소는 순서대로 처리됩니다. 하위 요소가 스택 맨 위로 이동되므로 하위 요소가 다음으로 처리됩니다.

    키를 고려하는 것도 가능하지만 스택을 처리하는 데는 다른 전략이 필요합니다. 하위 배열에서 가능한 중복 키를 처리해야하므로 필요합니다. 관련 질문에서 비슷한 대답 : PHP 키를 보존하면서 다차원 배열을 따라 가라.

    확실하지는 않지만 과거에 이것을 테스트했습니다. RecurisiveIterator는 재귀를 사용하므로 실제로 필요한 항목에 따라 다릅니다. 스택을 기반으로 재귀 적 반복자를 생성 할 수 있어야합니다.

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

    데모

    나는 지금까지 그것을 만들지 않았다. 좋은 아이디어라고 생각되는 RecursiveIterator를 기반으로 스택을 구현했다.

  5. ==============================

    5.

    재귀를 사용합니다. 다행스럽지 않은 방법을 보면서 바라는대로 복잡성이 얼마나 복잡한지를 알게되면 재귀에 대한 두려움이 사라질 것입니다.

    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>
    
  6. ==============================

    6.

    그냥 이것이 fold라고 지적 했으므로 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 ​​행을 따라 결합 함수를 요청합니다.

  7. ==============================

    7.

    간단하고 단 하나의 대답.

    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의 우려 / 문제 인용 :

    인용 Svish의 대답 :

  8. ==============================

    8.

    PHP 5.6 이상에서는 ... 연산자를 사용하여 외부 배열을 압축 해제 한 후 array_merge로 2 차원 배열을 병합 할 수 있습니다. 코드는 간단하고 명확합니다.

    $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
    )
    

    그러나 외부 배열에 숫자가 아닌 키가있을 때는 작동하지 않습니다. 이 경우 먼저 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
    )
    
  9. ==============================

    9.

    2 차원 배열 만 평평하게 만듭니다.

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

    10.

    이 솔루션은 비 재귀 적입니다. 요소의 순서는 다소 섞여 있음에 유의하십시오.

    function flatten($array) {
        $return = array();
        while(count($array)) {
            $value = array_shift($array);
            if(is_array($value))
                foreach($value as $sub)
                    $array[] = $sub;
            else
                $return[] = $value;
        }
        return $return;
    }
    
  11. ==============================

    11.

    다음과 같은 간단한 기능을 시도해보십시오.

    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',
    )
    
  12. ==============================

    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. ==============================

    13.

    트릭은 원본 및 대상 배열을 모두 참조로 전달합니다.

    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);
    
  14. ==============================

    14.

    /**
     * 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));
        }
    );
    

    요령

  15. ==============================

    15.

    당신은 ouzo 케이크로 그것을 할 수 있습니다 :

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

    여기를 보아라

  16. ==============================

    16.

    정말로 재귀가 마음에 들지 않는다면 대신 시도해보십시오 :)

    $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];
        }
    }
    

    참고 :이 간단한 버전에서는 배열 키를 지원하지 않습니다.

  17. ==============================

    17.

    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;
    }
    
  18. ==============================

    18.

    이 버전은 깊이, 얕은 또는 특정 수의 수준을 수행 할 수 있습니다.

    /**
     * @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;
    }
    
  19. ==============================

    19.

    여기에있는 코드는 무서운 것처럼 보입니다. 다차원 배열을 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;
    }
    
  20. ==============================

    20.

    아, 재귀없이! 심지어지도, 감소, 필터 재귀가 포함됩니다. 그것과 같은 몇 가지 해키 PHP는 방법을 사용하지 않는 한 불가능합니다. 진지하게, 아래의 코드에 관련된 루프가 없습니다, 좋은 배열 함수를 살해 한 사람은 죄송합니다 :)

    $arr=array(1,2,array(3,4, array(5,6,7), 8), 9);
    $json=json_encode($arr);
    $hacked_json=str_replace(['[',']'],"",$json);
    $hacked_array=json_decode('['.$hacked_json.']');
    echo "<pre>";
    print_r($hacked_array);
    

    산출

    Array
    (
        [0] => 1
        [1] => 2
        [2] => 3
        [3] => 4
        [4] => 1
        [5] => 2
        [6] => 6
        [7] => 7
        [8] => 8
        [9] => 9
    )
    

    중첩 된 키 값 쌍에 대해서도 작동합니다.

    $arr=array(1,2,array(3,4, array(array("s"=>array(1),"w"=>array('q'=>1,'v'=>12)),6,7), 8), 9);
    echo "<pre>";
    print_r($arr);
    $json=json_encode($arr);
    $hacked_json=str_replace(['[',']'],"",$json);
    $hacked_array=json_decode('['.$hacked_json.']');
    echo "<pre>";
    print_r(json_decode(json_encode($hacked_array), True));
    

    산출

    Array
    (
        [0] => 1
        [1] => 2
        [2] => 3
        [3] => 4
        [4] => Array
            (
                [s] => 1
                [w] => Array
                    (
                        [q] => 1
                        [v] => 12
                    )
    
            )
    
        [5] => 6
        [6] => 7
        [7] => 8
        [8] => 9
    )
    
  21. ==============================

    21.

    이것은 참조를 사용하여 내 솔루션입니다 :

    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>";
    
  22. ==============================

    22.

    <?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;
    }
    ?>
    
  23. ==============================

    23.

    다음은 간단한 접근법입니다.

    $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);
    
  24. ==============================

    24.

    HTML 다차원 배열을 HTML 입력 형식으로 표현해야했습니다.

    $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"
    }
    
  25. ==============================

    25.

    객체의 배열을 가지고 노드를 사용하여 객체를 병합하려면 다음 함수를 사용하십시오.

    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;
    }
    
  26. ==============================

    26.

    PHP 7부터, 내가 아는 것은 아닙니다. 나는 다차원 배열을 평평하게하고 중복 제거하기 위해 참조와 재귀 모두를 사용하고 다차원 배열 재구성을 위해 발견 된 각 복제물에 대해 가장 깊은 노드의 깊이를 보존하는 array_moonwalk를 호출하는 솔루션을 만들었습니다.

    foreach를 사용하지 않고 다른 깊이의 리프 노드 중복 제거를 처리하며 array_walk를 활용하는 유일한 해결책입니다. 성능을 테스트하지 않았습니다. YMMV.

  27. from https://stackoverflow.com/questions/1319903/how-to-flatten-a-multidimensional-array by cc-by-sa and MIT lisence