0

I have a multidimensional array that looks like this:

$trees = array(
    array(
        'name' => 'Parent',
        '__children' => array(
            array(
                'name' => 'Child'
            ),
            array(
                'name' => 'Second Child'
            )
        )
    )
);

The depth of the array is unknown and I need to recursively flatten it. So it looks more like this:

array(
  array(
    'name' => 'Parent' 
  ),
  array(
    'name' => 'Child' 
  ),
  array(
    'name' => 'Second Child' 
  )
)

I thought something like this might work:

public function flattenTree($trees, $tree = array())
{
    foreach($trees as $item){
        //$i = 1, 2, then 3
        $i = count($tree);
        $tree[$i] = array('name' => $item['name']);
        if(isset($item['__children']))
            $this->flattenTree($item['__children'], $tree);
    }
    return $tree;
}

But this is only gives me :(

Array
(
    [0] => Array
        (
            [name] => Parent
        )

)

I am unsure how to do this. Is it possible?

As a bonus I really need the output array to look like this(notice the name value changed) :)

array(
  array(
    'name' => 'Parent' 
  ),
  array(
    'name' => 'Parent Child' 
  ),
  array(
    'name' => 'Parent Second Child' 
  )
)

Thanks a ton for the help on this one. Looking forward to the solutions. I am stumped!

7
  • possible duplicate of How to Flatten a Multidimensional Array? Commented Nov 18, 2012 at 18:24
  • You can't specify an array element without a index. I'm sure you have got the correct output now Commented Nov 18, 2012 at 18:30
  • is your problem is missing child element from array? Commented Nov 18, 2012 at 18:32
  • @mohamed yes. For some reason the output does not contain the children Commented Nov 18, 2012 at 19:54
  • @JohnConde any chance you can take the example from that link and apply it here? I am not sure exactly how it would work, especially with building the full name based on the tree. Commented Nov 18, 2012 at 20:45

4 Answers 4

1

Ok I have given this a shot and although it might not be the cleanest solution I think it should get the job done:

function flattenRecursive(array &$flat, $parentkey, array $nested){

    $flag       = true;
    $prepend    = '';

    foreach( $nested as $k => $val ){
        if( is_array($val) ){

            if ( $k == '__children' && $flag) {
                $prepend = end($flat);
                $flag = true;
            } else {
                $flag = false;
            }

            flattenRecursive($flat, $prepend , $val);

        } else {

            $flat[] = $parentkey . ' ' . $val;

        }
    }
}

function flatten(array $nested){
    $flat = array();
    flattenRecursive($flat, '', $nested);
    return $flat;
}

On a test array (with extra nesting for extra testing) as follows

$trees = array(
            array(
                'name' => 'Parent',
                '__children' => array(
                    array(
                        'name' => 'Child',
                        '__children' => array(
                            array(
                                'name' => 'Nest One'
                            ),
                            array(
                                'name' => 'Nest Two'
                            )
                        )
                    ),
                    array(
                        'name' => 'Second Child'
                    )
                )
            )
        );

$result = flatten($trees);

the var_dump of $result looks like the following

array(5) {
  [0]=>
  string(7) " Parent"
  [1]=>
  string(13) " Parent Child"
  [2]=>
  string(22) " Parent Child Nest One"
  [3]=>
  string(22) " Parent Child Nest Two"
  [4]=>
  string(20) " Parent Second Child"
 }

Hopefully this was what you were looking for

Sign up to request clarification or add additional context in comments.

3 Comments

Hi Pankrates, I think you are on to something here. However this does not work for me b/c the array is more complex than this and using the foreach( $nested as $k => $val ) is throwing things off. Can you translate this so it uses foreach( $nested as $item ) instead?
Could you give an example array that is failing and where it is failing on? Find it hard to pinpoint what you mean exactly without example
See my answer, thanks again for your efforts! It helped a lot.
0

I ended up using something like this, with a lot of inspiration from @Pankrates answer. Thanks a lot.

$trees = $multidimensionalArray;
$flat = array();
$postRepository->flattenRecursive($flat, $trees);
//$flat is now a flattened version of $multidimensionalArray
var_dump($flat);


public function flattenRecursive(array &$flat, array $nested, $parentPrepend = false)
{
    foreach( $nested as $item ){
        $flat[] = array(
            'name' => ($parentPrepend) ? $parentPrepend . '/' . $item['name'] : $item['name']
        );
        $prepend = $parentPrepend ? $parentPrepend . '/' . $item['name'] : $item['name'];
        if(isset($item['__children']))
            $this->flattenRecursive($flat, $item['__children'], $prepend);
    }
}

Comments

0

code

<?php


$output_array = array();

$input_array  = array(
    array(
        'name'=>'Parent',
        '__children' => array(
            array(
                'name' => 'Child'
            ),
            array(
                'name' => 'Second Child'
            )
        )
    )
);

echo"<pre>";
print_r($input_array);
echo"</pre>";


function flatten($arr){
    global $output_array;
    if(is_array($arr)){
        foreach($arr as $key=>$value){
            if($key=="name" && !is_array($value)){
                $output_array[] = array($key=>$value);
            }
            elseif(is_array($value)){
                flatten($value);
            }
        }
    }
}

flatten($input_array);

echo"<pre>";
print_r($output_array);
echo"</pre>";

Output

//Input array
Array
(
    [0] => Array
        (
            [name] => Parent
            [__children] => Array
                (
                    [0] => Array
                        (
                            [name] => Child
                        )

                    [1] => Array
                        (
                            [name] => Second Child
                        )

                )

        )

)

//Output Array
Array
(
    [0] => Array
        (
            [name] => Parent
        )

    [1] => Array
        (
            [name] => Child
        )

    [2] => Array
        (
            [name] => Second Child
        )

)

Comments

0

I have similar logic problem, I used @Mike answer with some refactoring.

public function flattenRecursive(array &$flat, array $nested, $parentPrepend = false)
{
    foreach( $nested as $item ){
        $prepend = $parentPrepend ? $parentPrepend . '/' . $item['name'] : $item['name'];
        $flat[] = array(
            'name' => $prepend
        );
        if(isset($item['__children']))
            $this->flattenRecursive($flat, $item['__children'], $prepend);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.