views:

296

answers:

2

I have an array similar to this:

Array
(
    Array
    (
        [ID] => 1
        [parentcat_ID] => 0
    ),
    Array
    (
        [ID] => 2
        [parentcat_ID] => 0
    ),
    Array
    (
        [ID] => 6
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 7
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 8
        [parentcat_ID] => 6
    ),
    Array
    (
        [ID] => 9
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 13
        [parentcat_ID] => 7
    ),
    Array
    (
        [ID] => 14
        [parentcat_ID] => 8
    )

)

But I need a function to recursively put each item into a 'children' array inside the relevant parent array. So it would look more like this:

Array
(
    Array
    (
        [ID] => 1
        [parentcat_ID] => 0
        [children] => Array (
            Array
            (
                [ID] => 6
                [parentcat_ID] => 1
                [childen] => Array (
                    Array
                    (
                        [ID] => 8
                        [parentcat_ID] => 6
                        [children] => Array (
                             Array
                             (
                                 [ID] => 14
                                 [parentcat_ID] => 8
                             )
                        )
                    )
                )
            ),
            Array
            (
                [ID] => 7
                [parentcat_ID] => 1
                [children] => Array(
                     Array
                     (
                         [ID] => 13
                         [parentcat_ID] => 7
                     )
                ) 
            ),
            Array
            (
                [ID] => 9
                [parentcat_ID] => 1
            )

        )
    )
    Array
    (
        [ID] => 2
        [parentcat_ID] => 0

    )

)

I hope that makes sense!

+2  A: 

I recently answered a similar question. Here it is. Hope it suits your needs. If not, let me know, and I'll adjust it to your specs.

EDIT
Alright, here is the adjusted version that should suit your needs.

function generateMultiArray( array $flatArray )
{

    // initiate result array
    $multiArray = array();

    // iterate $flatArray
    foreach( $flatArray as $item )
    {
        // for convenience, initiate these vars
        $id = $item[ 'ID' ];
        $parentId = $item[ 'parentcat_ID' ];

        // initiate this item's children array;
        $item[ 'children' ] = array();

        // if parent doesn't exist yet, initiate it along with an empty 'children' array
        if( !isset( $multiArray[ $parentId ] ) )
        {
            $multiArray[ $parentId ] = array(
                'children' => array()
            );
        }

        // if this item is initiated already (as being a parent) merge it with the current item
        $multiArray[ $id ] = isset( $multiArray[ $id ] ) ? $multiArray[ $id ] + $item : $item;

        // add this item to the parents children collection by reference (for efficiency)
        $multiArray[ $parentId ][ 'children' ][ $id ] = &$multiArray[ $id ];

    }

    return $multiArray;
}

Mind you that this function also makes all items accessible as a root item of the result array with their ID as the index.

So, to access children of an item with arbitrary id n, you would do:

$multiArray = generateMultiArray( $yourFlatArray );
$children = $multiArray[ n ][ 'children' ]; // replace n with the id

EDIT 2
Forgot to intitiate children array for items that aren't a parent; added now. Otherwise it would result in a notice when trying to access it with:

$multiArray = generateMultiArray( $yourFlatArray );
$children = $multiArray[ $someIdWithoutChildren ][ 'children' ];
fireeyedboy
I kind of see where it's going but adjusting it would be incredibly handy :)
Joel
I see how it's working however it's not 'moving' the arrays into the the 'children' arrays, its duplicating them (or not unsetting items that are still at the root level)
Joel
@Joel: it's actually making references to them, not duplicates. I thought you might like the added convenience of having all items still accessible at root level also. I use this a lot myself because it makes looping through children of deeper nested items easy also.
fireeyedboy
Yeah that's true, I'll definitely keep this in my snippet stash :) Thank you.
Joel
+3  A: 
Max
Although your solution does the job, it has the disadvantage that it uses recursion, which isn't necessary per se.
fireeyedboy
@fireeyedboy: Iteration is human, recursion is devine. ;P Just kidding. There are of course other ways, too.
Max
This is a typical case where recursion is quite useful. Not to say it is necessary though.
Peter Lindqvist