PHP массив в многомерный массив

У меня есть массив в PHP с объектами, содержащимиЯ бы иparent_id, Все объекты без parent_id должны быть корневыми объектами в новом массиве.

Все объекты, которыеделать иметь parent_id должен быть помещен в правильный массив дочерних объектов объекта:

Итак, это мой оригинальный массив:

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

Вот как должен выглядеть новый массив:

$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
  ),
 );

Любая идея, как я мог это сделать?

 erisco28 сент. 2010 г., 16:54
Хм, я согласен с Филом Паффордом. Единственное полезное преимущество, которое я вижу, состоит в том, что получение всех детей для родителя может быть выполнено в постоянное время, а не линейно. Кроме того, переход от одного родителя к другому на самом деле становится сложнее.
 Yens28 сент. 2010 г., 16:43
Я думаю, что позже будет проще использовать его в качестве справочной таблицы, потому что я должен иметь возможность динамически добавлять / редактировать / удалять объекты и заменять их от одного родителя к другому
 Phill Pafford28 сент. 2010 г., 16:40
Зачем вам массив в другом формате? Похоже, у вас есть вся информация в первом массиве

Ответы на вопрос(1)

Решение Вопроса

Попробуйте что-то вроде этого:

// 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;
}

Используйте это так:

$nestedNodes = findChildren($nodeList);

Этот код рекурсивно ищет данныйparent_id в оригинале$nodeList, Если соответствующий узел найден, он ищет дочерние элементы этого узла и т. Д. Если нет детей по данномуparent_id найдены, пустой массив перенастраивается.

Вы можете уменьшить использование памяти в этом подходе, используя ссылки для$nodeList.

 jwueller28 сент. 2010 г., 17:00
@yens resmann: рекурсия действительно мощная, как вы можете видеть;) Однако используйте ее с осторожностью.
 Yens28 сент. 2010 г., 16:58
Спасибо! это именно то, что мне нужно! Не знал, что это так просто :)
 erisco28 сент. 2010 г., 17:03
+1, если вы можете сделать это с большей функциональностью.

Ваш ответ на вопрос