sistema proyecto multinivel genealogico ejemplos desplegable carpetas binario arboles arbol php arrays tree flat

proyecto - Construye un árbol desde una matriz plana en PHP



proyecto arboles php (10)

Aquí está mi solución, funciona idealmente, si suponemos que el nivel superior 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); } } }

He buscado en Internet y no he encontrado lo que estoy buscando. Tengo una matriz plana con cada elemento que contiene un ''id'' y un ''parent_id''. Cada elemento solo tendrá UN padre, pero puede tener varios hijos. Si parent_id = 0, se considera un elemento de nivel de raíz. Estoy tratando de obtener mi matriz plana en un árbol. Las otras muestras que he encontrado solo copian el elemento al padre, pero el original aún existe.

EDITAR

Cada elemento de la matriz de inicio se lee de un archivo XML separado. El archivo en sí tendrá ''0'' como el valor para parent_id si no tiene un padre. Las claves son en realidad cadenas.

Perdón por la confusión anterior. Espero que esto sea más claro:

/EDITAR

Mi matriz de inicio:

Array ( [_319_] => Array ( [id] => 0 [parent_id] => 0 ) [_320_] => Array ( [id] => _320_ [parent_id] => 0 ) [_321_] => Array ( [id] => _321_ [parent_id] => _320_ ) [_322_] => Array ( [id] => _322_ [parent_id] => _321_ ) [_323_] => Array ( [id] => _323_ [parent_id] => 0 ) [_324_] => Array ( [id] => _324_ [parent_id] => _323_ ) [_325_] => Array ( [id] => _325_ [parent_id] => _320_ ) )

La matriz resultante después de hacer el árbol:

Array ( [_319_] => Array ( [id] => _319_ [parent_id] => 0 ) [_320_] => Array ( [id] => _320_ [parent_id] => 0 [children] => Array ( [_321_] => Array ( [id] => _321_ [parent_id] => _320_ [children] => Array ( [_322_] => Array ( [id] => _322_ [parent_id] => _321_ ) ) ) [_325_] => Array ( [id] => _325_ [parent_id] => _320_ ) ) [_323_] => Array ( [id] => _323_ [parent_id] => 0 [children] => Array ( [_324_] => Array ( [id] => _324_ [parent_id] => _323_ ) ) )

¡Cualquier ayuda / guía es muy apreciada!

Algún código que tengo hasta ahora:

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; }


Aunque esta es una vieja pregunta, voy a publicar mi respuesta aquí:

/* 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 es PHP 5.5 pero puede crear el suyo fácilmente.


Desea buscar almacenar y cargar datos jerárquicos en MySQL ya que esto debería resolver algunos problemas. Supongo que la primera matriz representa datos tomados directamente de la base de datos.

Parece que está intentando usar el modelo de adyacencia para organizar sus datos en la estructura jerárquica. También hay otras formas de lograr esto utilizando el anidamiento. Si no está tomando estos datos de una base de datos, esto puede no ser tan útil.

Este enlace debería ayudarte: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/


Es posible construir la matriz fuente ligeramente diferente, puede usar esta función (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. Sistema de jerarquía más eficiente

Esta es mi solución, copie y optimice otras soluciones.

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; }


Esto funciona para mí:

$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);


La solución de ImmortalFirefly funciona, sin embargo, como señala, no salva a los primeros padres sin hijos. He editado la función para solucionar este problema:

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; }


Limpio, corto y sin lastre. Matriz de matrices en árbol:

class Mother { private $root; public function treeInit($array) { $this->root = new Child(); foreach($array as $value){ $this->root->treeClimb(array_reverse($value)); } return $this->root; } } class Child { private $children = []; public function treeClimb($arr) { if(count($arr) > 0) { $childTmp = array_pop($arr); if(!key_exists($childTmp,$this->children)) { $this->children[$childTmp] = new Child(); } $this->children[$childTmp]->treeClimb($arr); } } } $array = array(array(''obst'',''banae'',''krumm'',''gelb''), array(''obst'',''beere'',''him''), array(''obst'',''beere'',''brom''), array(''obst'',''banae'',''gerade''), array(''veg'',''carot'',''gerade'')); $obj = new Mother(); var_dump($obj->treeInit($array));


Puedo ver la lógica, excepto por esto en el resultado:

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

En mi humilde opinión, ¿parent_id = o, no debería ser [1] un niño de [0] aquí?

De todos modos, referencias al rescate:

$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);

Debido a que ha abusado 0 como un número ''mágico'' como raíz y como una identificación existente, ahora tenemos recursión en la rama id = 0. Añadiendo if($item[''parent_id'']!=$item[''id'']) before $tree[$item[''parent_id'']][''children''][] = &$tree[$item[''id'']]; podría evitar eso, pero no es bonito.


Olvidaste el unset() allí hermano.

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; }