How to “flatten” a multi-dimensional array to simple one in PHP?

前端 未结 23 2109
没有蜡笔的小新
没有蜡笔的小新 2020-11-22 01:03

It\'s probably beginner question but I\'m going through documentation for longer time already and I can\'t find any solution. I thought I could use implode for each dimensio

相关标签:
23条回答
  • 2020-11-22 01:07

    A new approach based on the previous example function submited by chaos, which fixes the bug of overwritting string keys in multiarrays:

    # Flatten a multidimensional array to one dimension, optionally preserving keys.
    # $array - the array to flatten
    # $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
    # $out - internal use argument for recursion
    
    function flatten_array($array, $preserve_keys = 2, &$out = array(), &$last_subarray_found) 
    {
            foreach($array as $key => $child)
            {
                if(is_array($child))
                {
                    $last_subarray_found = $key;
                    $out = flatten_array($child, $preserve_keys, $out, $last_subarray_found);
                }
                elseif($preserve_keys + is_string($key) > 1)
                {
                    if ($last_subarray_found)
                    {
                        $sfinal_key_value = $last_subarray_found . "_" . $key;
                    }
                    else
                    {
                        $sfinal_key_value = $key;
                    }
                    $out[$sfinal_key_value] = $child;
                }
                else
                {
                    $out[] = $child;
                }
            }
    
            return $out;
    }
    
    Example:
    $newarraytest = array();
    $last_subarray_found = "";
    $this->flatten_array($array, 2, $newarraytest, $last_subarray_found);
    
    0 讨论(0)
  • 2020-11-22 01:11

    Another method from PHP's user comments (simplified) and here:

    function array_flatten_recursive($array) { 
       if (!$array) return false;
       $flat = array();
       $RII = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
       foreach ($RII as $value) $flat[] = $value;
       return $flat;
    }
    

    The big benefit of this method is that it tracks the depth of the recursion, should you need that while flattening.
    This will output:

    $array = array( 
        'A' => array('B' => array( 1, 2, 3)), 
        'C' => array(4, 5) 
    ); 
    print_r(array_flatten_recursive($array)); 
    
    #Returns: 
    Array ( 
        [0] => 1 
        [1] => 2 
        [2] => 3 
        [3] => 4 
        [4] => 5 
    )
    
    0 讨论(0)
  • 2020-11-22 01:13

    With PHP 7, you can use generators and generator delegation (yield from) to flatten an array:

    function array_flatten_iterator (array $array) {
        foreach ($array as $value) {
            if (is_array($value)) {
                yield from array_flatten_iterator($value);
            } else {
                yield $value;
            }
        }
    }
    
    function array_flatten (array $array) {
        return iterator_to_array(array_flatten_iterator($array), false);
    }
    

    Example:

    $array = [
        1,
        2,
        [
            3,
            4,
            5,
            [
                6,
                7
            ],
            8,
            9,
        ],
        10,
        11,
    ];    
    
    var_dump(array_flatten($array));
    

    http://3v4l.org/RU30W

    0 讨论(0)
  • 2020-11-22 01:14

    Using higher-order functions (note: I'm using inline anonymous functions, which appeared in PHP 5.3):

    function array_flatten($array) {
        return array_reduce(
            $array,
            function($prev, $element) {
                if (!is_array($element))
                    $prev[] = $element;
                else
                    $prev = array_merge($prev, array_flatten($element));
                return $prev;
            },
            array()
        );
    }
    
    0 讨论(0)
  • 2020-11-22 01:14

    Someone might find this useful, I had a problem flattening array at some dimension, I would call it last dimension so for example, if I have array like:

    array (
      'germany' => 
      array (
        'cars' => 
        array (
          'bmw' => 
          array (
            0 => 'm4',
            1 => 'x3',
            2 => 'x8',
          ),
        ),
      ),
      'france' => 
      array (
        'cars' => 
        array (
          'peugeot' => 
          array (
            0 => '206',
            1 => '3008',
            2 => '5008',
          ),
        ),
      ),
    )
    

    Or:

    array (
      'earth' => 
      array (
        'germany' => 
        array (
          'cars' => 
          array (
            'bmw' => 
            array (
              0 => 'm4',
              1 => 'x3',
              2 => 'x8',
            ),
          ),
        ),
      ),
      'mars' => 
      array (
        'france' => 
        array (
          'cars' => 
          array (
            'peugeot' => 
            array (
              0 => '206',
              1 => '3008',
              2 => '5008',
            ),
          ),
        ),
      ),
    )
    

    For both of these arrays when I call method below I get result:

    array (
      0 => 
      array (
        0 => 'm4',
        1 => 'x3',
        2 => 'x8',
      ),
      1 => 
      array (
        0 => '206',
        1 => '3008',
        2 => '5008',
      ),
    )
    

    So I am flattening to last array dimension which should stay the same, method below could be refactored to actually stop at any kind of level:

    function flattenAggregatedArray($aggregatedArray) {
        $final = $lvls = [];
        $counter = 1;
        $lvls[$counter] = $aggregatedArray;
    
    
        $elem = current($aggregatedArray);
    
        while ($elem){
            while(is_array($elem)){
                $counter++;
                $lvls[$counter] = $elem;
                $elem =  current($elem);
            }
    
            $final[] = $lvls[$counter];
            $elem = next($lvls[--$counter]);
            while ( $elem  == null){
                if (isset($lvls[$counter-1])){
                    $elem = next($lvls[--$counter]);
                }
                else{
                    return $final;
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:14

    If you're interested in just the values for one particular key, you might find this approach useful:

    function valuelist($array, $array_column) {
        $return = array();
        foreach($array AS $row){
            $return[]=$row[$array_column];
        };
        return $return;
    };
    

    Example:

    Given $get_role_action=

    array(3) {
      [0]=>
      array(2) {
        ["ACTION_CD"]=>
        string(12) "ADD_DOCUMENT"
        ["ACTION_REASON"]=>
        NULL
      }
      [1]=>
      array(2) {
        ["ACTION_CD"]=>
        string(13) "LINK_DOCUMENT"
        ["ACTION_REASON"]=>
        NULL
      }
      [2]=>
      array(2) {
        ["ACTION_CD"]=>
        string(15) "UNLINK_DOCUMENT"
        ["ACTION_REASON"]=>
        NULL
      }
    }
    

    than $variables['role_action_list']=valuelist($get_role_action, 'ACTION_CD'); would result in:

    $variables["role_action_list"]=>
      array(3) {
        [0]=>
        string(12) "ADD_DOCUMENT"
        [1]=>
        string(13) "LINK_DOCUMENT"
        [2]=>
        string(15) "UNLINK_DOCUMENT"
      }
    

    From there you can perform value look-ups like so:

    if( in_array('ADD_DOCUMENT', $variables['role_action_list']) ){
        //do something
    };
    
    0 讨论(0)
提交回复
热议问题