ネストの深さが分からないデータ構造を平坦化したい場合は、1を使用できます。iteration_utilities.deepflatten
>>> from iteration_utilities import deepflatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
これはジェネレーターであるため、結果をにキャストするlist
か、明示的に反復処理する必要があります。
1 つのレベルのみを平坦化し、各項目自体が反復可能である場合は、iteration_utilities.flatten
which それ自体が単なる薄いラッパーである を使用することもできitertools.chain.from_iterable
ます。
>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
いくつかのタイミングを追加するだけです(この回答で提示された機能を含まなかったNico Schlömerの回答に基づいて):

これは、膨大な範囲の値に対応する対数対数プロットです。定性的な理由: 低いほど良い。
結果は、イテラブルに少数の内部イテラブルしか含まれていない場合はsum
最速になることを示していますが、長いイテラブルの場合はitertools.chain.from_iterable
、iteration_utilities.deepflatten
またはネストされた内包表記のみが合理的なパフォーマンスを発揮しitertools.chain.from_iterable
、最速であることが示されています (Nico Schlömer がすでに気づいているように)。
from itertools import chain
from functools import reduce
from collections import Iterable # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten
def nested_list_comprehension(lsts):
return [item for sublist in lsts for item in sublist]
def itertools_chain_from_iterable(lsts):
return list(chain.from_iterable(lsts))
def pythons_sum(lsts):
return sum(lsts, [])
def reduce_add(lsts):
return reduce(lambda x, y: x + y, lsts)
def pylangs_flatten(lsts):
return list(flatten(lsts))
def flatten(items):
"""Yield items from any nested iterable; see REF."""
for x in items:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
yield from flatten(x)
else:
yield x
def reduce_concat(lsts):
return reduce(operator.concat, lsts)
def iteration_utilities_deepflatten(lsts):
return list(deepflatten(lsts, depth=1))
from simple_benchmark import benchmark
b = benchmark(
[nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
argument_name='number of inner lists'
)
b.plot()
1 免責事項: 私はそのライブラリの作成者です