2010-03-18 12 views
5
def flattenList(toFlatten): 
final=[] 
for el in toFlatten: 
    if isinstance(el, list): 
    final.extend(flattenList(el)) 
    else: 
    final.append(el) 
return final 

Cuando no sé cuán profundamente anidarán las listas, esta es la única forma en que puedo pensar para hacer esto.¿Hay alguna manera funcional de hacerlo?

+0

Intente utilizar cuatro espacios en lugar de uno para su sangría. Es más legible y se ajustará a las pautas de estilo utilizadas para la mayoría del código Python. (La guía de estilo con la que se ajusta la mayoría del código de Python es http://www.python.org/dev/peps/pep-0008/) –

+0

Preguntas relacionadas: "Aplanar (una lista irregular) de listas en Python" http: // stackoverflow .com/questions/2158395/flatten-an-irregular-list-of-lists-in-python (enlaces a otras preguntas y buenas respuestas) "Aplanamiento de una lista superficial en python" http://stackoverflow.com/questions/406121/flattening-a-shallow-list-in-python (benchmarks) – jfs

Respuesta

2

Aquí es otra opción (aunque puede haber algo más limpia que la verificación de tipos, como las pruebas de si algo es iterable y por lo tanto no es un "átomo"):

def flatten(lst): 
    if not isinstance(lst,list): 
     return [lst] 
    else: 
     return reduce(lambda x,y:x+y,[flatten(x) for x in lst],[]) 

Se basa en algo esquema similar.

+1

'try: return reduce (...); excepto TypeError: return [lst] ' – Debilski

+0

Eso es perfecto. Gracias. – Ishpeck

+0

@mitmatt, 1) La función' lambda x, y: x + y' se llama 'operator.add'. 2) Su algoritmo es tan innecesariamente O (n * m) ish, cuando el algoritmo lineal es más obvio. –

7
  1. Debes evitar typechecking en Python. En este caso, esto significa evitar estructuras anidadas arbitrariamente donde se distingue por tipo. Puede construir su propio tipo de nodo que puede recorrer mediante los métodos otros que la verificación de tipo, como mirar un atributo específico.

  2. Para aplanar un nivel o exactamente n niveles, mira itertools.chain.from_iterable.

  3. No sé a qué te refieres con "funcional". Este código es bastante funcional: usa recursión (¡no en su honor!) Y no muta su argumento. (Estrictamente hablando, se hace uso de estado mutable para la construcción de una lista, pero eso es sólo la forma de hacerlo en Python.

  4. supongo que uno de los atributos más funcional sería la evaluación perezosa. Se podría implementar esta thusly

    def flatten(toFlatten): 
        for item in toFlatten: 
         if isinstance(item, list): # Ewww, typchecking 
          for subitem in flatten(item): # they are considering adding 
           yield subitem    # "yield from" to the language 
                  # to give this pattern syntax 
         else: 
          yield item 
    
  5. La recursividad es muy limitada en Python (al menos, en todas sus principales implementaciones) y generalmente se debe evitar para una profundidad arbitraria. Es bastante posible reescribir esto (y todo el código recursivo) para usar iteración, lo que hará más escalable (y menos funcional, que es algo bueno en Python, que no es especialmente adecuado para FP.)

+0

@Mike Graham: Quiero poder pasar listas que contienen listas que contienen listas, contener listas, etc., y aplanarlas hasta llegar a una sola resultado. Quiero: [1,2, [3,4,5,6], 7,8, [9,10, [11,12, [13, [14,15], 16], 17], 20 ]] Salir como: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20] Si sabía de antemano qué tan profundamente anidaban las listas, esto sería suficiente: def mergeLists (seq): \t reducción de retorno (lambda x, y: x + y, seq) – Ishpeck

+0

1) Deja de querer eso. Defina su estructura de manera diferente. 2) Su estrategia 'reduce' es multiplicativa en orden de Big-O; los algoritmos lineales son obvios. –

+0

Una respuesta más general: http://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists-in-python/2158532#2158532 – jfs

2

Bajo el doc para itertools, hay una función flatten()

+0

No en esa página no hay. –

+1

@Andrew Aylett, es una receta, no en el módulo en sí. Está en esa página. –

+0

@Mike: Admítelo, editó la documentación después de publicar mi comentario. No estoy seguro de cómo me lo perdí, no apareció cuando busqué la página en el trabajo: P. –

3

Esta respuesta explica por qué usted no desea utilizar para este reduce en Python.

Considere el fragmento

reduce(operator.add, [[1], [2], [3], [4], [5]]) 

¿Qué tiene que ver?

[1] + [2] => [1, 2] 
[1, 2] + [3] => This makes a new list, having to go over 1, then 2, then 3. [1, 2, 3] 
[1, 2, 3] + [4] => This has to copy the 1, 2, and 3 and then put 4 in the new list 
[1, 2, 3, 4] + [5] => The length of stuff I have to copy gets bigger each time! 

Este comportamiento cuadrática es completamente evitable: la solución original (y cualquier número de otras soluciones) no forma estos pasos de copiado intermedio.

Cuestiones relacionadas