2012-03-19 23 views
6

Necesito ayuda para atravesar una estructura de árbol de una manera profunda. No puedo idear un algoritmo para hacerlo correctamente.Javascript Tree Traversal Algorithm

Mi entrada es la siguiente:

[ 
    ["A", "B", "C"], 
    ["1", "2"], 
    ["a", "b", "c", "d"] 
] 

La salida debe tomar la forma:

[ 
    "A/1/a", "A/1/b", "A/1/c", "A/1/d", 
    "A/2/a", "A/2/b", "A/2/c", "A/2/d", 
    "B/1/a", "B/1/b", "B/1/c", "B/1/d", 
    "B/2/a", "B/2/b", "B/2/c", "B/2/d", 
    "C/1/a", "C/1/b", "C/1/c", "C/1/d", 
    "C/2/a", "C/2/b", "C/2/c", "C/2/d" 
] 
+0

Esto se puede hacer, pero es una poco complicado. ¿Hay alguna manera de reorganizar tus datos? Tendrá problemas para coordinar cuál de 'A B C' corresponde a' 1 2' y cuál de 'a b c d'; su información esperada parece que sigue una regla bastante extraña. +1 para dar datos esperados, sin embargo. – Bojangles

+0

Claro. Puedo manipular la entrada de cualquier manera. ¿Qué forma sería preferible? – Adam

+0

La manera más fácil que se me ocurre es tener una matriz secundaria en lugar de una matriz hermana. Esto es mucho más fácil de recorrer como una estructura de árbol. – Bojangles

Respuesta

7

Esto debería hacer el trabajo:

function traverse(arr) { 
 
    var first = arr[0]; 
 
    var ret = []; 
 
    if (arr.length == 1) { 
 
    for (var i = 0; i < first.length; i++) { 
 
     ret.push(first[i]); 
 
    } 
 
    } else { 
 
    for (var i = 0; i < first.length; i++) { 
 
     var inn = traverse(arr.slice(1)); 
 
     for (var j = 0; j < inn.length; j++) { 
 
     ret.push(first[i] + '/' + inn[j]); 
 
     } 
 
    } 
 
    } 
 
    return ret; 
 
} 
 

 
var inp = [ 
 
    ["A", "B", "C"], 
 
    ["1", "2"], 
 
    ["a", "b", "c", "d"] 
 
]; 
 

 
var out = traverse(inp); 
 

 
console.log(out);

3

Lo que estamos buscando es el producto cartesiano de una lista de listas, que ha sido asked antes de. Los préstamos de la respuesta aceptada por esa pregunta, usted puede hacer esto en Javascript 1.7:

function product() { 
    return Array.prototype.reduce.call(arguments, function(as, bs) { 
     return [a.concat(b) for each (a in as) for each (b in bs)]; 
    }, [[]]); 
}; 

function convert(lst) { 
    var solution = []; 
    for (var i = 0; i < lst.length; i++) { 
    solution.push(lst[i][0] + "/" + lst[i][1] + "/" + lst[i][2]); 
    } 
    return solution; 
}; 

convert(product(["A", "B", "C"], ["1", "2"], ["a", "b", "c", "d"])); 

> ["A/1/a", "A/1/b", "A/1/c", "A/1/d", 
    "A/2/a", "A/2/b", "A/2/c", "A/2/d", 
    "B/1/a", "B/1/b", "B/1/c", "B/1/d", 
    "B/2/a", "B/2/b", "B/2/c", "B/2/d", 
    "C/1/a", "C/1/b", "C/1/c", "C/1/d", 
    "C/2/a", "C/2/b", "C/2/c", "C/2/d"] 
+0

Creo que deberías incluir el enlace permanente, porque en teoría pueden cambiar la respuesta aceptada y publicar 100 respuestas más (y sería bastante difícil encontrarlo en ese momento) – ajax333221

+0

@ ajax333221 estoy de acuerdo, agregué el enlace permanente como sugeriste. –

+1

Esto es más elegante y más general, pero no resuelve el problema específico y hay un error en la versión actual. – Adam