я пытаюсь создать иерархию многомерного массива из простого массива, который содержит пары идентификаторов категорий и родительских идентификаторов. Категории могут быть родительскими и подкатегориями одновременно. Базовые категории имеют родителя 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
Список входных узлов в заданном порядке — «дочерний» => «родительский» порядок, что необычно, это нормально, просто помните, что при обработке …
Обработать входные данные:
$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
Если вы хотите сформировать рекурсивный массив, вы можете обратиться на эту страницу
Рекурсивная функция для генерации многомерного массива из результата базы данных
это может вам очень помочь. Благодарю.