Intereting Posts
Использование PHPass для хеш-пароля Propel.xml дает мне ошибку – Недопустимый тип для пути "propel.database.connections.cfs.attributes". Ожидаемый массив, но получил строку Загрузка файла конфигурации .user.ini PHP с использованием внутреннего сервера PHP 5.4? OAuth – секрет потребителя в приложениях с открытым исходным кодом Как получить путь к серверу в веб-каталоге Symfony2 изнутри контроллера? Примечание. Неопределенный индекс: HTTP_REFERER Отправить письмо с шаблоном, используя php Рассчитайте расстояние Google от входного адреса и всего адреса от сервера MySQL с помощью jQuery ajax.get Как работает editData? Предупреждение: Неверный сдвиг смещения строки в обработчике C: \ wamp \ www \ whois \ whois \ whois.gtld.php в строке 57 Как перенаправить маршрут с помощью метода контроллера Что значит запустить PHP-функцию с амперсандом? PHP заменяет строку после использования file_get_contents Удаленная отладка PHP: XDebug не может подключиться к клиенту JetBrains php Storm Facebook FQL. Какой самый простой способ получить все изменения страницы в одном запросе, упорядоченном по дате / времени?

Создание дерева из плоского массива в PHP

Я просмотрел интернет и не совсем нашел то, что искал. У меня есть плоский массив с каждым элементом, содержащим «id» и «parent_id». Каждый элемент будет иметь только один родительский элемент, но может иметь несколько дочерних элементов. Если parent_id = 0, он считается элементом уровня корня. Я пытаюсь получить свой плоский массив в дерево. Другие образцы, которые я нашел, только копируют элемент в родительский, но оригинал все еще существует.

РЕДАКТИРОВАТЬ

Каждый элемент стартового массива считывается из отдельного XML-файла. Сам файл будет иметь значение «0» в качестве значения parent_id, если у него нет родителя. Ключи на самом деле являются строками.

Прошу прощения за замешательство раньше. Надеюсь, это более понятно:

/РЕДАКТИРОВАТЬ

Мой начальный массив:

 массив
 (
     [_319_] => Массив
         (
             [id] => 0
             [parent_id] => 0
         )

     [_320_] => Массив
         (
             [id] => _320_
             [parent_id] => 0
         )

     [_321_] => Массив
         (
             [id] => _321_
             [parent_id] => _320_
         )

     [_322_] => Массив
         (
             [id] => _322_
             [parent_id] => _321_
         )

     [_323_] => Массив
         (
             [id] => _323_
             [parent_id] => 0
         )

     [_324_] => Массив
         (
             [id] => _324_
             [parent_id] => _323_
         )

     [_325_] => Массив
         (
             [id] => _325_
             [parent_id] => _320_
         )
 ) 

Получившийся массив после дерева:

 массив
 (
     [_319_] => Массив
         (
             [id] => _319_
             [parent_id] => 0
         )

     [_320_] => Массив
         (
             [id] => _320_
             [parent_id] => 0
             [children] => Массив
                 (
                     [_321_] => Массив
                         (
                             [id] => _321_
                             [parent_id] => _320_
                             [children] => Массив
                                 (
                                     [_322_] => Массив
                                         (
                                             [id] => _322_
                                             [parent_id] => _321_
                                         )
                                 )
                         )
                     [_325_] => Массив
                         (
                             [id] => _325_
                             [parent_id] => _320_
                         )
                 )
     [_323_] => Массив
         (
             [id] => _323_
             [parent_id] => 0
             [children] => Массив
                 (
                     [_324_] => Массив
                         (
                             [id] => _324_
                             [parent_id] => _323_
                         )
                 )
         )

Любая помощь / руководство очень ценится!

Некоторый код, который у меня есть до сих пор:


         function buildTree (array & $ elements, $ parentId = 0) {
         $ branch = array ();

         foreach ($ elements as $ element) {
             if ($ element ['parent_id'] == $ parentId) {
                 $ children = $ this-> buildTree ($ elements, $ element ['id']);
                 if ($ children) {
                     $ element ['children'] = $ children;
                 }
                 $ branch [] = $ element;
             }
         }

         return $ branch;
     }

Вы забыли unset() в там брата.

 function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as $element) { if ($element['parent_id'] == $parentId) { $children = buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[$element['id']] = $element; unset($elements[$element['id']]); } } return $branch; } не function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as $element) { if ($element['parent_id'] == $parentId) { $children = buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[$element['id']] = $element; unset($elements[$element['id']]); } } return $branch; } 

Решение ImmortalFirefly работает, однако, как указывает mrded, это не спасает первых родителей без детей. Я отредактировал функцию, чтобы исправить эту проблему:

 function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as &$element) { if ($element['parent_id'] == $parentId) { $children = buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[$element['id']] = $element; unset($element); } } return $branch; } с function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as &$element) { if ($element['parent_id'] == $parentId) { $children = buildTree($elements, $element['id']); if ($children) { $element['children'] = $children; } $branch[$element['id']] = $element; unset($element); } } return $branch; } 

Это работает для меня:

 $index=array(); $tree=array(); foreach ($ori as $key=>$var) { $var=array_shift($ori); if ($var['id']==0) $var['id']=$key; if ((string)$var['parent_id']==='0') { $tree[$key]=$var; $index[$key]=&$tree[$key]; } else if (isset($index[$var['parent_id']])) { if (!isset($index[$var['parent_id']]['children'])) $index[$var['parent_id']]['children']=array(); $index[$var['parent_id']]['children'][$key]=$var; $index[$key]=&$index[$var['parent_id']]['children'][$key]; } else { array_push($ori,$var); } } unset($index); print_r($tree); с $index=array(); $tree=array(); foreach ($ori as $key=>$var) { $var=array_shift($ori); if ($var['id']==0) $var['id']=$key; if ((string)$var['parent_id']==='0') { $tree[$key]=$var; $index[$key]=&$tree[$key]; } else if (isset($index[$var['parent_id']])) { if (!isset($index[$var['parent_id']]['children'])) $index[$var['parent_id']]['children']=array(); $index[$var['parent_id']]['children'][$key]=$var; $index[$key]=&$index[$var['parent_id']]['children'][$key]; } else { array_push($ori,$var); } } unset($index); print_r($tree); 

Я вижу логику, за исключением этого в результате:

 Array ( [0] => Array ( [id] => 0 [parent_id] => 0 ) [1] => Array ( [id] => 1 [parent_id] => 0 ) 

ИМХО, является parent_id = o, не должен ли [1] быть ребенком [0] здесь?

Во всяком случае, ссылки на спасение:

 $tree = array(); foreach($inputarray as $item){ if(!isset($tree[$item['id']])) $tree[$item['id']] = array(); $tree[$item['id']] = array_merge($tree[$item['id']],$item); if(!isset($tree[$item['parent_id']])) $tree[$item['parent_id']] = array(); if(!isset($tree[$item['parent_id']]['children'])) $tree[$item['parent_id']]['children'] = array(); $tree[$item['parent_id']]['children'][] = &$tree[$item['id']]; } $result = $tree[0]['children']; unset($tree); print_r($result); с $tree = array(); foreach($inputarray as $item){ if(!isset($tree[$item['id']])) $tree[$item['id']] = array(); $tree[$item['id']] = array_merge($tree[$item['id']],$item); if(!isset($tree[$item['parent_id']])) $tree[$item['parent_id']] = array(); if(!isset($tree[$item['parent_id']]['children'])) $tree[$item['parent_id']]['children'] = array(); $tree[$item['parent_id']]['children'][] = &$tree[$item['id']]; } $result = $tree[0]['children']; unset($tree); print_r($result); 

Поскольку вы злоупотребляли 0 как «магическим» номером как root, так и существующим id, теперь мы имеем рекурсию в ветке id = 0. Добавление if($item['parent_id']!=$item['id']) перед $tree[$item['parent_id']]['children'][] = &$tree[$item['id']]; может предотвратить это, но это не очень.

Возможно, исходный массив немного отличается, вы можете использовать эту функцию (parent_id, id, title):

 $q = mysql_query("SELECT id, parent_id, name FROM categories"); while ($r = mysql_fetch_row($q)) { $names[$r[0]] = $r[2]; $children[$r[0]][] = $r[1]; } function render_select($root=0, $level=-1) { global $names, $children; if ($root != 0) echo '<option>' . strrep(' ', $level) . $names[$root] . '</option>'; foreach ($children[$root] as $child) render_select($child, $level+1); } echo '<select>'; render_select(); echo '</select>'; 
  1. Более эффективная иерархическая система

Хотя это старый вопрос, я собираюсь опубликовать свой ответ здесь:

 /* assuming top level pid = 0 */ $rows = array ( array ( 'id' => 1, 'pid' => 0 ), /* ... */ ); /* make id become array key */ $rows = array_column ( $rows, null, 'id' ); foreach ( $rows as $key => $val ) { if ( $val ['pid'] ) { if ( isset ( $rows [$val ['pid']] )) { $rows [$val ['pid']]['children'][] = &$rows [$key]; } } } foreach ( $rows as $key => $val ) { if ( $val ['pid'] ) unset ( $rows [$key] ); } 

array_column – это PHP 5.5, но вы можете сделать свой собственный легко.

Вы хотите смотреть на хранение и загрузку иерархических данных в MySQL, поскольку я должен решить несколько проблем. Я предполагаю, что первый массив представляет данные, полученные непосредственно из базы данных?

Похоже, вы пытаетесь использовать модель смежности для организации своих данных в структуре иерархии. Есть и другие способы достижения этой цели с помощью гнездования. Если вы не берете эти данные из базы данных, это может быть не так полезно.

Эта ссылка должна помочь вам: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Вот мое решение, идеально работает, если предположить, что верхний уровень parent_id = 0:

 function MakeTree($arr){ $parents_arr=array(); foreach ($arr as $key => $value) { $parents_arr[$value['pid']][$value['id']]=$value; } $tree=$parents_arr['0']; $this->createTree($tree, $parents_arr); return $tree; } function createTree(&$tree, $parents_arr){ foreach ($tree as $key => $value) { if(!isset($value['children'])) { $tree[$key]['children']=array(); } if(array_key_exists($key, $parents_arr)){ $tree[$key]['children']=$parents_arr[$key]; $this->createTree($tree[$key]['children'], $parents_arr); } } } 

Это мое решение, копирование и оптимизация других решений.

 function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as $key => $element) { if ($element['parent_id'] == $parentId) { $children = $this->buildTree($elements, $key); if ($children) { $element['children'] = $children; } $branch[$key] = $element; unset($elements[$key]); } } return $branch; } не function buildTree(array &$elements, $parentId = 0) { $branch = array(); foreach ($elements as $key => $element) { if ($element['parent_id'] == $parentId) { $children = $this->buildTree($elements, $key); if ($children) { $element['children'] = $children; } $branch[$key] = $element; unset($elements[$key]); } } return $branch; }