0

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?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Kyobul
  • 759
  • 1
  • 7
  • 17

5 Answers5

1

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);
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
0

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);
K.A.F.
  • 2,277
  • 1
  • 16
  • 17
0

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);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
-1

You could try

foreach($toplevel as $a){
    $finalarray = $a[0];
}
Limiter
  • 497
  • 3
  • 11
-1

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];  
Joe T
  • 2,300
  • 1
  • 19
  • 31