Я пытаюсь создать многомерную иерархию массивов из простого массива, который содержит пары идентификаторов категорий и идентификаторов родительских элементов. Категории могут быть родителями и подкатегорией одновременно. Базовые категории имеют родительский элемент 0 (= родительский). Например:
# cat_id => parent_id $initialArray = array( 1 => 0, 2 => 1, 3 => 2, 4 => 0, 5 => 4, 6 => 0 );
Из этого я хотел бы получить массив, который представляет такую структуру:
Я не буду знать содержимое $initialArray
заранее.
Я попытался посмотреть другие подобные вопросы, но я не мог найти ответа. Пожалуйста помоги!
Ну, мне кажется, вам нужна рекурсивная функция. Предполагая, что все имеет родительский элемент или значение, начинающееся с базового уровня 0, я перегруппировал массив, чтобы все родительские идентификаторы отображали их дочерние элементы, а не наоборот. После этого я создал рекурсивную функцию.
$initialArray = array( 1 => 0, 2 => 1, 3 => 2, 4 => 0, 5 => 4, 6 => 0 ); // resituate the array $parent_ids = array(); foreach ($initialArray as $category_id => $parent_id) { if (!isSet($parent_ids[$parent_id])) { $parent_ids[$parent_id] = array(); } $parent_ids[$parent_id][] = $category_id; } // end_array is the result $end_array = array(); /** * Takes the key of the parent, the current set that it's working off of, the list of parent ids for reference * and the current place in the end result array, acting recursively */ function recursive($parent_key, $current_set, $parent_ids, $end_array) { foreach ($current_set as $parent_value) { if (!isSet($parent_ids[$parent_value])) { $end_array[$parent_key][] = $parent_value; } else { // if the parent_value is found in parent_ids, pass those values to the same function and the current end_array position $end_array[$parent_key] = recursive($parent_value, $parent_ids[$parent_value], $parent_ids, $end_array[$parent_key]); } } return $end_array; } // start with the top most element $end_array = recursive(key($parent_ids), current($parent_ids), $parent_ids, $end_array); print '<pre>'. print_r($parent_ids, true). print_r($end_array,true). '</pre>' ;
Выходы:
// resituated array Array ( [0] => Array ( [0] => 1 [1] => 4 [2] => 6 ) [1] => Array ( [0] => 2 ) [2] => Array ( [0] => 3 ) [4] => Array ( [0] => 5 ) ) // the end result Array ( [0] => Array ( [1] => Array ( [2] => Array ( [0] => 3 ) ) [4] => Array ( [0] => 5 ) [5] => 6 ) )
Я знаю, поздно вечером, но выглядит интересно …
/* * This is a 'multiway' tree where: * a 'parent' can have any number of 'child' nodes * therefore the 'parent node' must look like: * [parentId] => array() * * where [parentId] is the index of an array; */
Он будет вставлять один узел за раз, начиная с корневого узла. Это может стать очень дорогостоящим для больших деревьев.
Рабочий пример: Viper-7.com
Процедура, которая выполняет работу:
/** * Insert: Find the 'parent' node * if child not found then insert a 'node' * * @param array node passed by reference as the new node will be inserted * @param integer $parentId - root Id must be the lowest value * @param integer $childId * @return boolean true if parentId found and processed */ function insertNode(&$node, $parentId, $childId) { if (isset($node[$parentId])) { // this node will be processed if (!isset($node[$parentId][$childId])) { $node[$parentId][$childId] = array(); // add child node return true; } return true; // end of processing } // check all the children of this node... foreach($node as &$child) { // need the reference if (insertNode($child, $parentId, $childId)) { return true; } } return false; // parentId not in the tree }
Заметки:
The node to be processed is passed by reference. The processing will end when the 'parent' id is found
Список входных узлов как заданный является «child» => «parent», что необычно, это нормально, просто помните, что в обработке …
Обработать входные данные:
$theTree = array(current($links) => array()); // root // insert all the child nodes into the tree foreach($links as $childId => $parentId) { $inserted = insertNode($theTree, $parentId, $childId); } // output the tree echo '<pre>', 'Children are in the same order as the input array.', '<br />'; print_r($theTree); echo '</pre>';
Список входных данных должен быть взломан, чтобы «дерево» было загружено таким образом, чтобы родительский элемент добавляемого потомка должен быть уже в дереве. Я предполагаю, что список входных данных уже в нужном порядке
Тестирование данных, сортировка и отображение:
# cat_id => parent_id $links = array( 1 => 0, 2 => 1, 3 => 2, 4 => 0, 5 => 4, // multiple children 11 => 4, 99 => 4, 13 => 11, 6 => 0 );
Вывод, я добавил поддерево оригинального ввода …
Children are in the same order as the input array. Array ( [0] => Array ( [1] => Array ( [2] => Array ( [3] => Array ( ) ) ) [4] => Array ( [5] => Array ( ) [11] => Array ( [13] => Array ( ) ) [99] => Array ( ) ) [6] => Array ( ) ) )
Есть ли способ изменить способ создания массива? Поскольку у вас есть это сейчас, будет больше хлопот, тогда стоит попробовать и создать то, что вы хотите.
Кроме того, вы можете попробовать создать что-то вроде этого:
$menu = array( 0 => array(0, 1, 2, 3), 1 => array(0, 1), );
Разрешая простой цикл следующим образом:
<ul> <?php foreach ($menu as $parent => $subs) : ?> <li> <?php echo $parent; ?> <ul> <?php foreach ($subs as $index => $val): ?> <li> <?php echo $val; ?> </li> <?php endforeach; ?> </ul> </li> <?php endforeach; ?> </ul>
Вышеупомянутый синтаксис шаблонов, я уверен, что все мы знаем, что это такое, и теперь я собираюсь это объяснить.
Или простой цикл будет выглядеть так:
echo "<ul>"; foreach($menu as $parent => $subs){ echo "<li>"; echo $parent; echo "<ul>"; foreach($subs as $index => $val) { echo "<li>"; echo $val; echo "</li>"; } echo "</ul>"; echo "</li>"; } echo "</ul>";
Получите ваш список:
<?php $initialArray = array( 1 => 0, 2 => 1, 3 => 2, 4 => 0, 5 => 4, 6 => 0 ); $menus = array(); function generateMenus($start) { global $initialArray; foreach($initialArray as $k => $v) { if($start == $v) { $menus[] = $k; } } return $menus; } $final = array(); foreach($initialArray as $key => $value) { $final[$value] = generateMenus($value); } echo '<ul>'; function generateList($start) { global $final; echo '<li>'.$start.'</li>'; if(!empty($final[$start])) { echo '<ul>'; foreach($final[$start] as $v) { generateList($v); } echo '</ul>'; } } generateList(0); echo '</ul>'; ?>
Вы можете создать такой массив
$initialArray = array(); $initialArray[parent_id][cat_id]='your_value'; //$initialArray[0][0] ... and then increasing
Если вы хотите сформировать рекурсивный массив, вы можете ссылаться на эту страницу
Рекурсивная функция для генерации многомерного массива из результата базы данных
это может вам помочь. Благодарю.