Иерархия категорий из массива (идентификатор кошки => идентификатор родителя)

я пытаюсь создать иерархию многомерного массива из простого массива, который содержит пары идентификаторов категорий и родительских идентификаторов. Категории могут быть родительскими и подкатегориями одновременно. Базовые категории имеют родителя 0 (= нет родителя). Например:

# cat_id => parent_id
$initialArray = array(
1 => 0,
2 => 1,
3 => 2,

4 => 0,
5 => 4,

6 => 0
);

Из этого я хотел бы получить массив, который представляет такую ​​структуру:

  • 1
    • 2
      • 3
  • 4
    • 5
  • 6

Я не буду знать содержание $initialArray заранее.

Я пытался посмотреть на другие подобные вопросы, но я не мог найти ответ. Пожалуйста помоги!

1

Решение

Ну, мне кажется, вам нужна рекурсивная функция. Предполагая, что у всех есть родительский элемент или значение, начинающееся с базового уровня 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
)

)
1

Другие решения

Я знаю, опоздал на вечеринку, но выглядит интересно …

/*
* 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
(
)
)
)
2

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

В качестве альтернативы, вы можете попробовать сгенерировать что-то вроде этого:

$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>";
1

Получите ваш список:

<?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>';?>

Будет производить

1

Вы можете сделать массив, как это

$initialArray = array();
$initialArray[parent_id][cat_id]='your_value';   //$initialArray[0][0] ... and then increasing
0

Если вы хотите сформировать рекурсивный массив, вы можете обратиться на эту страницу

Рекурсивная функция для генерации многомерного массива из результата базы данных

это может вам очень помочь. Благодарю.

0
По вопросам рекламы [email protected]