リストの内包表記を使用して反復可能リストをフラット化する簡単な方法はありますか。それができない場合、パフォーマンスと読みやすさのバランスを取りながら、このような浅いリストをフラット化する最善の方法は何だと思いますか。
次のように、ネストされたリストの理解を使用してこのようなリストをフラット化しようとしました。
[image for image in menuitem for menuitem in list_of_menuitems]
しかし、私はそこで多様性に困っていますNameError
。なぜならname 'menuitem' is not defined
、 グーグルで検索し、Stack Overflow で調べた後、次のreduce
文で目的の結果が得られました。
reduce(list.__add__, map(lambda x: list(x), list_of_menuitems))
list(x)
しかし、 x は Django オブジェクトなので、その呼び出しが必要なので、このメソッドはかなり読みにくくなりますQuerySet
。
結論:
この質問に貢献してくださった皆様に感謝します。私が学んだことの要約は次のとおりです。また、他の人がこれらの観察を追加したり修正したりしたい場合に備えて、これをコミュニティ ウィキにしています。
元のreduceステートメントは冗長なので、次のように記述した方がよいでしょう。
>>> reduce(list.__add__, (list(mi) for mi in list_of_menuitems))
これはネストされたリストの理解のための正しい構文です(素晴らしい要約dF!):
>>> [image for mi in list_of_menuitems for image in mi]
しかし、これらの方法はどちらも、以下を使用するほど効率的ではありませんitertools.chain
。
>>> from itertools import chain
>>> list(chain(*list_of_menuitems))
chain.from_iterable
@cdleary が指摘しているように、次のように使用して * 演算子マジックを回避する方がおそらく良いでしょう。
>>> chain = itertools.chain.from_iterable([[1,2],[3],[5,89],[],[6]])
>>> print(list(chain))
>>> [1, 2, 3, 5, 89, 6]
ベストアンサー1
データ構造のフラット化されたバージョンを反復処理するだけで、インデックス可能なシーケンスが必要ない場合は、次のことを検討してください。itertools.chain と会社。
>>> list_of_menuitems = [['image00', 'image01'], ['image10'], []]
>>> import itertools
>>> chain = itertools.chain(*list_of_menuitems)
>>> print(list(chain))
['image00', 'image01', 'image10']
QuerySet
これは反復可能なものであれば何でも動作します。これには、質問で使用していると思われるDjango の iterable も含まれます。
編集:いずれにしても、これはおそらく、reduce と同じくらい良いでしょう。reduce では、拡張されるリストにアイテムをコピーする際に同じオーバーヘッドが発生するからです。最後にchain
実行した場合にのみ、この (同じ) オーバーヘッドが発生します。list(chain)
メタ編集:実際には、元のリストを一時的に拡張するときに作成した一時リストを破棄するため、質問で提案された解決策よりもオーバーヘッドが少なくなります。
編集:JFセバスチャンは言う itertools.chain.from_iterable
解凍を回避し、*
魔法を避けるためにそれを使用する必要がありますが、タイムイットアプリパフォーマンスの違いはごくわずかです。