¿Cómo puedo usar una lista de comprensión para ampliar una lista en python?

No tengo experiencia en Python, y a menudo escribo códigos que (simplificados) se ven así:

accumulationList = [] for x in originalList: y = doSomething(x) accumulationList.append(y) return accumulationList 

Luego, después de que mi prueba pasa, me refactorizo ​​a

 return [doSomething(x) for x in originalList] 

Pero supongamos que resulta un poco diferente, y mi bucle se parece a esto:

 accumulationList = [] for x in originalList: y = doSomething(x) accumulationList.extend(y) return accumulationList 

donde la lista doSomething devuelve una lista. ¿Cuál es la forma más pythonica de lograr esto? Obviamente, la lista de comprensión anterior daría una lista de listas.

Mucho más simple y limpio con la lista de comprensión:

 [y for x in originalList for y in doSomething(x)] 

¿Te refieres a algo como esto?

 accumulationList = [] for x in originalList: accumulationList.extend(doSomething(x)) return accumulationList 

o código más corto (pero no óptimo):

 return sum((doSomething(x) for x in originalList), []) 

o lo mismo:

 return sum(map(doSomething, originalList), []) 

Gracias a @eyquem por la pista (si usas Python 2.x):

 import itertools as it return sum(it.imap(doSomething, originalList), []) 

El operador de adición en el lugar de Python ( += , disponible como iadd en el módulo del operator ) es equivalente a .extend para la lista. Combínalo con reduce para obtener lo que quieres.

 import operator reduce(operator.iadd, (doSomething(x) for x in originalList) , accumulation_list) 

Creo que las respuestas relacionadas con add o iadd se ejecutan en tiempo cuadrático, lo que probablemente no sea bueno. Lo intentaria

 from itertools import chain accumulation_list = list(chain.from_iterable(doSomething(x) for x in originalList)) 

No creo que haya una syntax especial para este caso. Pero podrías hacer el bucle for más corto:

 accumulationList += doSomething(x) 

Si insistes, podrías usar la progtwigción funcional para aplanar la lista:

 result = reduce(lambda a,b: a+b, [[i,i*2] for i in range(3)]) 

Pero no llamaría a este python, creo que es más difícil de leer que un bucle for.

Funcionalmente , puedes usar itertools.chain con el map . Para una lista de entrada L :

 res = list(chain.from_iterable(map(doSomething, L))) 

Si necesita un iterador, simplemente elimine la list llamadas. Aquí hay una demostración:

 def doSomething(value): return [value * i for i in range(1, 4)] def original(originalList): accumulationList = [] for x in originalList: y = doSomething(x) accumulationList.extend(y) return accumulationList def new(L): return list(chain.from_iterable(map(doSomething, L))) x = [1, 2, 3] assert original(x) == new(x) print(new(x)) [1, 2, 3, 2, 4, 6, 3, 6, 9]