Tengo una clase de árbol general con: myTree = new Tree(string), appendChildNode(node), createChildNode(string), funciones myTree.print() y atributos myTree.name, myTree.children , etc.
También tengo un mapa múltiple con datos que quiero descomponer y poner en un objeto de árbol. Supongamos que los datos no tienen círculos. Mi idea es dejar que la recursión construya las subramas. Por alguna razón, la recursión no funciona y no puedo entender por qué. El retorno dentro de forEach me da un 'indefinido'
mi multimapa:
aaaa -> [b, c, d] c -> [f] f -> [g] r -> [p]Entonces mi árbol resultante para "aaaa" debería ser:
aaaa bcd f gmi función principal:
myMultiMap ... <multimap defined here> myTree = new Tree('End2End') // my tree object // lets just pick the 'aaaa' to start with myMultiMap.get('aaaa').forEach((entry) => { newNode = new Tree(entry) myTree.appendChildNode(recurse(newNode)) }) // show the tree after it was built myTree.print()función recursiva
function recurse (node) { // if the element is in the multimap, it has one or more children if(myMultiMap.has(node.name)) { // iterate through all children of the node in the multimap myMultiMap.get(node.name).forEach((child) => { // build a new node from the child newChildnode = new Tree(child); // build a subtree recursively, since this child could have children itself return node.appendChildNode(recurse(newChildnode)) }) // if the node is not in the multimap, thus it has no children, so just return the node } else { return node } }Información: tomé la implementación de este árbol: https://github.com/beforesemicolon/tutorials-files/blob/master/tree-generic.js
Usando una implementación de árbol trivial y usando un Mapa de cadenas a arreglos de cadenas en lugar de su implementación MultiMap, podemos ver la estructura con bastante claridad:
const tree = (name, children) => ({name, children}) const mapToTree = (multiMap) => (root) => tree (root, (multiMap .get (root) || []) .map (mapToTree (multiMap))) const myMultiMap = new Map ([ ['aaaa', ['b', 'c', 'd']], ['c', ['f']], ['f', ['g']], ['r', ['p']] ]) console .log (mapToTree (myMultiMap) ('aaaa')) .as-console-wrapper {max-height: 100% !important; top: 0} Si desea un nodo contenedor externo, End2End , podemos envolver una llamada más al tree :
const myTree = tree ('End2End', mapToTree (myMultiMap) ('aaaa'))El retorno dentro de forEach me da un 'indefinido'
Sí, no puede return de una devolución de llamada forEach . Pero eso no es lo que quieres hacer de todos modos. En cambio, después de realizar el ciclo, desea return node :
function recurse(node) { if (myMultiMap.has(node.name)) { myMultiMap.get(node.name).forEach((child) => { const newChildnode = new Tree(child); node.appendChildNode(recurse(newChildnode)) }) return node; } else { return node; } }o simplemente
function recurse(node) { if (myMultiMap.has(node.name)) { myMultiMap.get(node.name).forEach((child) => { const newChildnode = new Tree(child); node.appendChildNode(recurse(newChildnode)) }) } return node; }Alternativamente, no devuelva el nodo en absoluto, solo escriba
function recurse(node) { if (myMultiMap.has(node.name)) { myMultiMap.get(node.name).forEach((child) => { const newChildnode = new Tree(child); recurse(newChildnode); node.appendChildNode(newChildnode); }) } } o tal vez mejor, en su lugar, mueva la creación del nodo dentro de la función recurse :
function recurse(name) { const node = new Tree(name); if (myMultiMap.has(name)) { myMultiMap.get(name).forEach((child) => { node.appendChildNode(recurse(child)) }) } return node; }Por cierto, en su código principal no necesita duplicar el ciclo. simplificarlo a
const myMultiMap = …; // multimap defined here const myTree = recurse(new Tree('aaaa')); myTree.print();o para mi última versión, respectivamente
const myMultiMap = …; // multimap defined here const myTree = recurse('aaaa'); myTree.print();