Three options:
You could sum the nested lists; sum()
takes a second argument, a starting value, set that to an empty list:
>>> sum(myList[0], [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
This works because sum()
is essentially implemented as a loop:
def sum(values, start=0):
total = start
for value in values:
total += value
return total
which works with list concatenation, provided the start value is a list object itself. 0 + [1, 2, 3]
would not work, but [] + [1, 2, 3]
works just fine.
You could use reduce()
with operator.add()
, which is essentially the same as sum()
, minus the requirement to give a start value:
from operator import add
reduce(add, myList[0])
operator.add()
could be replaced with lambda a, b: a + b
or with list.__add__
if imports are to be avoided at all cost.
As the nested input list grows, operator.iadd()
(in-place add, for lists the equivalent of list.extend()
) will rapidly become a faster option:
from operator import iadd
reduce(add, myList[0], [])
but this does need an empty list to start with.
You could chain the lists using itertools.chain.from_iterable()
:
>>> from itertools import chain
>>> list(chain.from_iterable(myList[0]))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
All three solutions require that you use indexing to remove the outermost list, although you can also pass the one element in myList
as a single argument to chain.from_iterable()
with list(chain.from_iterable(*myList))
as well.
Of these options, reduce(add, ...)
is the fastest:
>>> timeit.timeit("sum(myList[0], [])", 'from __main__ import myList')
1.2761731147766113
>>> timeit.timeit("reduce(add, myList[0])", 'from __main__ import myList; from operator import add')
1.0545191764831543
>>> timeit.timeit("reduce(lambda a, b: a.extend(b) or a, myList[0], [])", 'from __main__ import myList')
2.225532054901123
>>> timeit.timeit("list(chain.from_iterable(myList[0]))", 'from __main__ import myList; from itertools import chain')
2.0208170413970947
and comparing iadd
versus add
:
>>> timeit.timeit("reduce(add, myList[0])", 'from __main__ import myList; from operator import add')
0.9298770427703857
>>> timeit.timeit("reduce(iadd, myList[0], [])", 'from __main__ import myList; from operator import iadd')
1.178157091140747
>>> timeit.timeit("reduce(add, myListDoubled)", 'from __main__ import myList; myListDoubled = myList[0] + myList[0]; from operator import add')
2.3597090244293213
>>> timeit.timeit("reduce(iadd, myListDoubled, [])", 'from __main__ import myList; myListDoubled = myList[0] + myList[0]; from operator import iadd')
1.730151891708374
You could use recursion to avoid using a loop, to make this work for arbitrarily nested lists:
def flatten(lst):
try:
return flatten(sum(lst, []))
except TypeError:
return lst
Demo:
>>> flatten(myList)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> flatten(myList + myList)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]