php - Flatten multidimensional array to 3 levels preserving the first level keys

379

I have a nested multidimensional array like this:

$array = [
    1 => [
        [
            ['catName' => 'Villes', 'catUrl' => 'villes', 'parent' => 151],
            [
                ['catName' => 'Administratif', 'catUrl' => 'territoire', 'parent' => 37],
                [
                    ['catName' => 'Gegraphie', 'catUrl' => 'geographie', 'parent' => 0]
                ]
            ]
        ]
    ]
];

I would like to flatten it to a simpler structure, like this:

array (
  1 => 
  array (
    0 => 
    array (
      'catName' => 'Villes',
      'catUrl' => 'villes',
      'parent' => 151,
    ),
    1 => 
    array (
      'catName' => 'Administratif',
      'catUrl' => 'territoire',
      'parent' => 37,
    ),
    2 => 
    array (
      'catName' => 'Gegraphie',
      'catUrl' => 'geographie',
      'parent' => 0,
    ),
  ),
)

I suppose it would work with some recursive function, but my skills in there are not my best. How can I accomplish this?

479

Answer

Solution:

Here is one way to do it. This function will collapse each level:

function collapse($array) {
    // End of recursion is indicated when the first element is not an array.
    if (!is_array(reset($array))) {
        return array($array);
    }
    // Otherwise, collapse it.
    return array_reduce($array, function($carry, $item) {
        // Recursively collapse each item and merge them together.
        return array_merge($carry, collapse($item));
    }, array());
}

It can be applied to your array like this:

$collapsed = array_map("collapse", $array);
721

Answer

Solution:

It's not pretty, but it works:

$deeparray = array();  // the really nested array goes here
$flattened = array();

function flatten($item,$key)
{
  global $flattened;
  if ( $key == 'catName' || $key == 'catUrl' || $key == 'parent' )
  {
    if ( sizeof( $flattened) == 0 )
    {  $flattened[] = array( $key=>$item );  }
    else
    {
      $last = array_pop($flattened);
      if ( array_key_exists($key,$last) )
      {
        $flattened[] = $last;
        $flattened[] = array( $key=>$item );
      }
      else
      {
        $last[ $key ] = $item;
        $flattened[] = $last;
      }
    }
  }
}



array_walk_recursive($deeparray,'flatten',$flattened);

$flattened = array($flattened);
312

Answer

Solution:

Make a recursive call on each first level element.

Within the recursive function, first isolate the non-iterable elements and push them as a single new row into the desired result array. Then execute the recursive function on each iterable element on that level.

It is important to "pass data back up" with each each recursive call so that all deep data can be collected and returned in the top-level/finished array.

The global-level foreach modifies by reference so that the assignment of$parent mutates the original input array.

Code: (Demo)

function flattenRows($array) {
    $result = [];
    $scalars = array_filter($array, 'is_scalar');
    if ($scalars) {
        $result[] = $scalars;
    }
    foreach (array_diff_key($array, $scalars) as $item) {
        $result = array_merge($result, flattenRows($item));
    }
    return $result;
}

$result = [];
foreach ($array as &$parent) {
    $parent = flattenRows($parent);
}
var_export($array);
693

Answer

Solution:

You could try

foreach($toplevel as $a){
    $finalarray = $a[0];
}
187

Answer

Solution:

if the structure will always be the same as what you've shown then i think you can do this:

$newarray[1][0] = $oldarray[1][0][0];  
$newarray[1][1] = $oldarray[1][0][1][0];  
$newarray[1][2] = $oldarray[1][0][1][1][0];  

People are also looking for solutions to the problem: How to change PHPs behavior to echo an HTML comment on every include() and require()

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.