При получении иерархической структуры от MySQL (таблица с одним столбцом ID и одним столбцом PARENT, показывающим иерархические отношения), я отображаю результат в перечислимый массив следующим образом (для этого примера, числа произвольны):
Array ( [3] => Array ( [7] => Array () ), [7] => Array ( [8] => Array () ) )
Уведомление 3 является родителем 7, и 7 родитель 8 (это могло продолжиться и на; и любой родитель мог иметь несколько детей).
Я хотел уменьшить этот массив во вложенный многомерный массив следующим образом:
Array ( [3] => Array ( [7] => Array ( [8] => Array () ) ) )
Таким образом, каждому НОВОМУ идентификатору автоматически присваивают пустой массив. Независимо, дети любого идентификатора будут продвинуты в массив их родителя.
Смотрите на следующую иллюстрацию для дальнейшего разъяснения:
сопроводительный текст http://img263.imageshack.us/img263/4986/array.gif
Это, вероятно, приведет к сложной рекурсивной операции, так как я всегда должен проверять, существует ли родитель с каким-либо определенным идентификатором уже (и если так, продвиньте значение в его массив).
Существует ли встроенная функция php, которая может помочь мне с этим? У Вас есть какая-либо идея относительно того, как пойти о построении этого? Если это имеет значение я использую это для созданного панель навигации в Wordpress (который может содержать категории, подкатегории, сообщения... по существу что-либо).
Идея состоит в том, что вы сохраняете вспомогательный массив со всеми найденными узлами (родительскими и дочерними). Значения этих массивов являются ссылками, которые подтверждают ваш результат.
Это строит дерево за линейное время (array_key_exists выполняет поиск в хеш-таблице, которая в среднем составляет O (1)):
//table contains (id, parent)
$orig = array(
11 => 8,
7 => 3,
8 => 7,
99 => 8,
16 => 8,
);
$childrenTable = array();
$result = array();
foreach ($orig as $n => $p) {
//parent was not seen before, put on root
if (!array_key_exists($p, $childrenTable)) {
$childrenTable[$p] = array();
$result[$p] = &$childrenTable[$p];
}
//child was not seen before
if (!array_key_exists($n, $childrenTable)) {
$childrenTable[$n] = array();
}
//root node has a parent after all, relocate
if (array_key_exists($n, $result)) {
unset($result[$n]);
}
$childrenTable[$p][$n] = &$childrenTable[$n];
}
unset($childrenTable);
var_dump($result);
дает
array(1) {
[3]=>
array(1) {
[7]=>
array(1) {
[8]=>
array(3) {
[11]=>
array(0) {
}
[99]=>
array(0) {
}
[16]=>
array(0) {
}
}
}
}
}
EDIT: unset $ childrenTable
в конце для снять флажки ссылок. На практике вы, вероятно, все равно захотите выполнить операцию внутри функции.
Этот вопрос и ответы на него должны быть вам полезны: превратить результат базы данных в массив.
Обязательно прочитайте PDF-презентацию @Bill Karwin, в частности, темы, касающиеся таблицы Closure.