次のようなリストがあります。
[[1,2,3],[1,2],[1,4,5,6,7]]
それを[1,2,3,1,2,1,4,5,6,7]
にフラット化したい
numpyを使用せずにこれを行う軽量関数はありますか?
Numpy( ndarray.flatten
)を使用しない場合、 chain.from_iterable
を使用できます。これはitertools.chain
の代替コンストラクターです。
>>> list(chain.from_iterable([[1,2,3],[1,2],[1,4,5,6,7]]))
[1, 2, 3, 1, 2, 1, 4, 5, 6, 7]
また、python 2およびfunctools.reduce
in 3で短いリストに対してより効率的なreduce
を使用できます(長いリストには使用しないでください):
In [4]: from functools import reduce # Python3
In [5]: reduce(lambda x,y :x+y ,[[1,2,3],[1,2],[1,4,5,6,7]])
Out[5]: [1, 2, 3, 1, 2, 1, 4, 5, 6, 7]
または、少し速い方法として、lambda
の代わりにoperator.add
を使用します。
In [6]: from operator import add
In [7]: reduce(add ,[[1,2,3],[1,2],[1,4,5,6,7]])
Out[7]: [1, 2, 3, 1, 2, 1, 4, 5, 6, 7]
In [8]: %timeit reduce(lambda x,y :x+y ,[[1,2,3],[1,2],[1,4,5,6,7]])
789 ns ± 7.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [9]: %timeit reduce(add ,[[1,2,3],[1,2],[1,4,5,6,7]])
635 ns ± 4.38 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
または、別のまだPython的なアプローチとして、list comprehensionを使用できます:
[j for sub in [[1,2,3],[1,2],[1,4,5,6,7]] for j in sub]
基準:
:~$ python -m timeit "from itertools import chain;chain.from_iterable([[1,2,3],[1,2],[1,4,5,6,7]])"
1000000 loops, best of 3: 1.58 usec per loop
:~$ python -m timeit "reduce(lambda x,y :x+y ,[[1,2,3],[1,2],[1,4,5,6,7]])"
1000000 loops, best of 3: 0.791 usec per loop
:~$ python -m timeit "[j for i in [[1,2,3],[1,2],[1,4,5,6,7]] for j in i]"
1000000 loops, best of 3: 0.784 usec per loop
sum
を使用した@Willの回答のベンチマーク(短いリストでは高速ですが、長いリストでは高速ではありません):
:~$ python -m timeit "sum([[1,2,3],[4,5,6],[7,8,9]], [])"
1000000 loops, best of 3: 0.575 usec per loop
:~$ python -m timeit "sum([range(100),range(100)], [])"
100000 loops, best of 3: 2.27 usec per loop
:~$ python -m timeit "reduce(lambda x,y :x+y ,[range(100),range(100)])"
100000 loops, best of 3: 2.1 usec per loop
このようなリストの場合、私のお気に入りのすてきな小さなトリックは、sum
;を使用することです。
sum
にはオプションの引数sum(iterable [, start])
があるため、次のことができます。
list_of_lists = [[1,2,3], [4,5,6], [7,8,9]]
print sum(list_of_lists, []) # [1,2,3,4,5,6,7,8,9]
これは、+
演算子はたまたまリストの連結演算子であり、開始値は[]
-空のリスト。
しかし、 sum
のドキュメントは itertools.chain
代わりに、はるかに明確です。
これは特定のケースで機能します。再帰関数は、複数レベルのネストされた反復可能オブジェクトがある場合に最適に機能します。
def flatten(input):
new_list = []
for i in input:
for j in i:
new_list.append(j)
return new_list