2011-07-27 19 views
7

Estoy atascado en un problema pequeño pero difícil desde ayer.Python - Iteración sobre listas anidadas

Lo que tengo es una (posiblemente infinito) Lista anidado como este:

[1,[2,[3,4]]] 
or [[1,2],[3,4]] and so on. 

En cada nivel las listas consisten en dos sublistas, (no hice uso de tuplas porque las listas probable que obtener una longitud arbitraria en el próximo paso) Ahora quiero insertar un elemento en cada posición posible en esta lista y devolver una lista de todas las posibles posiciones de inserción. Así que si inserto 5, mi salida debería verse como:

[ [5,[1,[2,[3,4]]]], 
[1,[5,[2,[3,4]]]], 
[1,[2,[5,[3,4]]]], 
[1,[2,[[3,5],4]]], 
[1,[2,[3,[4,5]]]] ] 

El fondo: Estoy tratando de construir un árbol filogenético mediante la adición de un taxón a la vez. Cada taxón debe insertarse en la posición en la que se ajuste mejor.

Lo que tengo ahora es:

def get_trees(nwklist,newid): 
    if not isinstance(nwklist,list): 
     return [newid,nwklist] 
    else: 
     return [newid,nwklist],[get_trees(nwklist[0],newid),nwklist[1]],[nwklist[0],get_trees(nwklist[1],newid)] 

que no produce la salida que quiero, pero llega un poco cerca.

([5, [1, [2, [3, 4]]]], 
[[5, 1], [2, [3, 4]]], 
[1, ([5, [2, [3, 4]]], [[5, 2], [3, 4]], [2, ([5, [3, 4]], [[5, 3], 4], [3, [5, 4]])])]) 

Debería haber una solución fácil, quizás con funciones lambda, pero simplemente no la veo.

Christoph

+6

Seguramente está reinventando la rueda. Hay paquetes para el manejo de árboles filogenéticos en Python, como Phylo de Biopython (http://www.biopython.org/wiki/Phylo) o dendropy (http://pypi.python.org/pypi/DendroPy) –

+0

Sólo detalle: su la lista puede tener * profundidad arbitraria *, pero no profundidad * infinita *. Al menos, no sé cómo podría. –

+0

"Cada taxón debe insertarse en el lugar donde se ajuste mejor". Esto suena como intentar construir un árbol de unión de vecinos, que es un mal plan. Busque literatura adicional sobre la mejor forma de construir árboles filogenéticos y por qué la forma más fácil también es la peor. – pyvi

Respuesta

2

que haría uso de un generador:

def gen_trees(nwklist, newid): 
    yield [newid] + [nwklist] 
    if isinstance(nwklist, list): 
    for i in xrange(len(nwklist)): 
     for l in gen_trees(nwklist[i], newid): 
     yield nwklist[:i] + [l] + nwklist[i+1:] 
    yield [nwklist] + [newid] 

for l in gen_trees([1,[2,[3,4]]] , 5): 
    print l 

Tenga en cuenta que esto devuelve más árboles de los que aparecen en su ejemplo:

[5, [1, [2, [3, 4]]]] 
[[5, 1], [2, [3, 4]]] 
[[1, 5], [2, [3, 4]]] 
[1, [5, [2, [3, 4]]]] 
[1, [[5, 2], [3, 4]]] 
[1, [[2, 5], [3, 4]]] 
[1, [2, [5, [3, 4]]]] 
[1, [2, [[5, 3], 4]]] 
[1, [2, [[3, 5], 4]]] 
[1, [2, [3, [5, 4]]]] 
[1, [2, [3, [4, 5]]]] 
[1, [2, [[3, 4], 5]]] 
[1, [[2, [3, 4]], 5]] 
[[1, [2, [3, 4]]], 5] 

Por lo que yo puedo ver, esto ahder a los requisitos establecidos. Si hay algunos requisitos no declarados que no obtuve (por ejemplo, si el primer elemento de cada sublista tiene que ser un escalar), aclare y actualizaré la solución.

+0

¡Gracias! Eso se ve muy bien. Más que enumeré, olvidé mencionar que la orden no es importante, así que [1, [[5, 2], [3, 4]]] [1, [[2, 5], [3 , 4]]] son básicamente el mismo árbol. – Christoph

+0

Y si elimino la segunda línea de rendimiento [nwklist] + [newid], obtengo exactamente lo que quería. ¡Muchas gracias! – Christoph

Cuestiones relacionadas