1

I have an array in php with Objects containing an id and a parent_id. All Objects without a parent_id should be the root Objects in a new array.

All Objects that do have a parent_id should be pushed in the correct Object's children array:

So this is my original array:

array
  0 => 
    object(Node)[528]
      protected 'id' => int 1
      protected 'parent_id' => null
  1 =>
   object(Node)[529]
      protected 'id' => int 2
      protected 'parent_id' => null
  2 => 
   object(Node)[530]
      protected 'id' => int 3
      protected 'parent_id' => 1
  3 =>  
   object(Node)[531]
      protected 'id' => int 4
      protected 'parent_id' => 1
  4 =>  
  object(Node)[532]
      protected 'id' => int 5
      protected 'parent_id' => 4
  5 =>  
  object(Node)[533]
      protected 'id' => int 6
      protected 'parent_id' => 4

this is what the new array should look like:

$nodes = array(
  array(
   'id' => 1,
   'parent_id' => null,
   'children' => array(
    array(
     'id' => 3,
     'parent_id' => 1,
     'children' => null
    ),
    array(
     'id' => 4,
     'parent_id' => 1,
     'children' => array(
      array(
       'id' => 5,
       'parent_id' => 4
      ),
      array(
       'id' => 6,
       'parent_id' => 5
      ), 
     )
    ),
   ),
  ),
  array(
   'id' => 2,
   'parent_id' => null,
   'children' => null
  ),
 );

Any Idea how I could do this?

3
  • Why do you need the array in a different format? Looks like you have all the information in the first array Commented Sep 28, 2010 at 14:40
  • I think it's easier to use it as a reference table later on, because I have to be able to add / edit / delete objects dynamically and replace them from one parent to another Commented Sep 28, 2010 at 14:43
  • Hm, I agree with Phill Pafford. The only useful benefit I can see is that obtaining all the children for a parent could be done in constant time rather than linear. Also, moving from one parent to another actually becomes harder. Commented Sep 28, 2010 at 14:54

1 Answer 1

5

Try something like this:

// collects all nodes that belong to a certain parent id
function findChildren($nodeList, $parentId = null) {
    $nodes = array();

    foreach ($nodeList as $node) {
        if ($node['parent_id'] == $parentId) {
            $node['children'] = findChildren($nodeList, $node['id']);
            $nodes[] = $node;
        }
    }

    return $nodes;
}

Use it like this:

$nestedNodes = findChildren($nodeList);

This code recursively searches for the given parent_id in the original $nodeList. If a matching node is found, it searches for the children of this node, and so on. If no children for the given parent_id are found, an empty array is retuned.

You could reduce the memory usage of this approach by using references for $nodeList.

2
  • Thanks! this is exactly what I needed! Didn't know it was this simple :) Commented Sep 28, 2010 at 14:58
  • @yens resmann: Recursion is really powerful, as you can see ;) Use it with caution, though. Commented Sep 28, 2010 at 15:00

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.