Tengo una matriz treeFlatNode y quiero estructurarla en formato de árbol. o puedo mostrar esta matriz en el árbol directamente en angular.
data=[ { expandable: true level: 0 name: "2021-12-31" path: null }, { expandable: false level: 2 name: "A.txt" path: "2021-12-31/B/C/A.txt" } ] required format tree=[ name:"2021-12-03", children:[ name:"B", children:[{ name:"C" children:[{ name:"A.txt" children:[] }] }] ] ]Entonces, para transformar su estructura de datos a la deseada, puede usar la siguiente función (con comentarios =)):
transform(data){ const tree = []; for (let node of data) { // If there's no path it's a parent node // but add it only if it doesn't exist yet if (node.path === null && tree.every(n => n.name !== node.name)) { tree.push({ name: node.name, children: [] }); continue; } // Extract name of parent node and other nodes const [parentNodeName, ...pathElems]: string[] = node.path.split('/'); // Look-up for the parent node let parentNode = tree.find(t => t.name === parentNodeName); // If parent doesn't exist yet, so we create it here if (!parentNode) { parentNode = { name: parentNodeName, children: [] } } let children = parentNode.children; // If the level of the node is relevant // otherwise simply iterate over all pathElems for(let i = 0; i <= node.level; i ++) { let child = children.find(c => c.name === pathElems[i]); // If the child doesn't exist yet - create it if (!child) { child = { name: pathElems[i], children: [] } children.push(child); children = child.children; continue; } // Child does exist, so use it's children for the next iteration children = child.children; } } return tree; } Y puede llamar a esta función, por ejemplo, en ngOnInit :
ngOnInit() { this.tree = this.transform(this.data); }Podría usar un objeto ( map ) que asigna una (sub) ruta a un nodo en el árbol final. Si aún no existe, se agrega a los hijos de los padres.
Como su estructura de árbol en realidad representa un bosque (puede haber múltiples raíces), nombraría la variable de resultado forest en lugar de tree
Retazo:
function toForest(data) { const roots = []; const map = {}; for (const obj of data) { let key = ""; let children = roots; for (const name of (obj.path ?? obj.name).split("/")) { let child = map[key += "/" + name]; if (!child) children.push(map[key] = child = { name, children: [] }); ({children} = child); } } return roots; } // Example run let data = [{expandable: true,level: 0,name: "2021-12-31",path: null}, {expandable: false,level: 2,name: "A.txt",path: "2021-12-31/B/C/A.txt"}]; let forest = toForest(data); console.log(forest);No uso Angular, pero si solo necesita convertir su plano en anidado:
var data = [ { expandable: true, level: 0, name: "2021-12-31", path: null }, { expandable: false, level: 2, name: "A.txt", path: "2021-12-31/B/C/A.txt" } ] var to_nested = function(flat) { var nested = [] var cache = {} var l = flat.length var cache_assert = function(name) { if (cache[name] == null) { cache[name] = { name: name, children: [] } } } for (var i = 0; i < l; i++) { var current_node = flat[i] cache_assert(current_node.name) if (current_node.path == null) { nested.push(cache[current_node.name]) } else { var names = current_node.path.split("/") var parent_name = names.shift() cache_assert(parent_name) names.forEach(function(name) { cache_assert(name) cache[parent_name].children.push(cache[name]) parent_name = name }) } } return nested } var a = to_nested(data) console.log('a: ', a) console.log('a: ', a[0].children) console.log('a: ', a[0].children[0].children)Y si quieres volver a piso:
var level = 0 var cache = []; cache[level] = a.slice(0) var parent = []; parent[level] = null var index = []; index[level] = 0 while (level >= 0) { var node = cache[level][index[level]] if (node != null) { console.log('node: ', node) if ( node['children'] != null && Object.prototype.toString.call(node['children']) === '[object Array]' && node['children'].length ) { level++ index[level] = 0 parent[level] = Object.assign({}, node) delete parent[level]['children'] cache[level] = node['children'].slice(0) } else { index[level]++ } } else { parent[level] = null level-- index[level]++ } }