views:

30

answers:

2

I have a flat array that I'm trying to make multidimensional. Basically, I want to find the items that have parents and create a subarray for that parent id. Right now (and this is simplified), it looks like this:

Array 
(
  [0] => stdClass Object
  (
    [id] => 1
    [parent] => 0
    [name ] => Parent1
  )

  [1] => stdClass Object
  (
    [id] => 7
    [parent] => 1
    [name] => Child1
  )

  [2] => stdClass Object
  (
    [id] => 9
    [parent] => 1
    [name] => Child2
  )

  [3] => stdClass Object
  (
    [id] => 2
    [parent] => 0
    [name ] => Parent2
  )

  [4] => stdClass Object
  (
    [id] => 88
    [parent] => 2
    [name] => Childof2
  )
)

I'm trying to make this:

Array 
(
  [0] => stdClass Object
  (
    [id] => 1
    [parent] => 0
    [name ] => Parent1
    [children] => stdClass Object
    (
       [1] => stdClass Object
       (
         [id] => 7
         [parent] => 1
         [name] => Child1
       )

       [2] => stdClass Object
       (
          [id] => 9
          [parent] => 1
          [name] => Child2
       )
    )
  )

  [1] => stdClass Object
  (
    [id] => 2
    [parent] => 0
    [name ] => Parent2
    [children] => stdClass Object
    (
       [0] => stdClass Object
       (
         [id] => 88
         [parent] => 2
         [name] => Childof2
        )
    )
  )
)
A: 

A dirty and slow way using recursion is here for you. The pseudocode:

$objects;// Your plain list.
$root = (object) array('id' => 0);

appendChildren($root, $objects);

function appendChildren(&$node, $objects)
{
    foreach($objects as $obj)
    {
        if($obj->parent == $node->id)
        {
            if(!isset($node->children))
                $node->children = array();

            $node->children[] = $obj;
            appendChildren($obj, $objects);
        }
    }
}
scaryzet
A: 
<?php

/**
 * This function should be efficient for large sets.
 * It loops a maximum of 3n times, each pass is cheap,
 * and it can work with multiple levels of children,
 * parents and grandparents.
 */
function makeHierarchical($flatListOfObjects) {
  // Create new reference list keyed on "id",
  // assuming "id" is a positive integer.
  $idList = array();
  foreach ($flatListOfObjects as $o) {
    $idList[$o->id] = $o;
  }

  // Connect children with their parents, but don't remove
  // them from top level yet, because they themselves might
  // also be parents with children to be attached.
  foreach ($idList as $o) {
    if ($o->parent > 0) {
      // Add as a child item to the children list of the parent.
      $idList[$o->parent]->children[] = $o;
    }
  }

  // Remove children from top level of the list.
  foreach ($idList as $key => $o) {
    if ($o->parent > 0) {
      unset($idList[$key]);
    }
  }

  // Return our newly created hierarchical list.
  return $idList;
}

/**
 * Test Functions
 */
function test_makeHierarchical() {
  function makeObj($id, $name, $parent=0) {
    $o = new stdClass();
    $o->id = $id;
    $o->name = $name;
    $o->parent = $parent;
    return $o;
  }

  $flatList[] = makeObj(1, 'Parent1');
  $flatList[] = makeObj(7, 'Child1', 1);
  $flatList[] = makeObj(9, 'Child2', 1);
  $flatList[] = makeObj(2, 'Parent2');
  $flatList[] = makeObj(88, 'Childof2', 2);

  print_r($flatList);
  $newList = makeHierarchical($flatList);
  print_r($newList);
}

test_makeHierarchical();

?>
msmithgu