1. ホーム
  2. python

[解決済み] Pythonで浅いリストを平坦にする [重複] [重複

2022-03-23 09:55:05

質問

リスト内包で反復可能なリストを平坦化する簡単な方法はありますか?あるいは、そうでない場合、パフォーマンスと可読性のバランスを取りながら、このような浅いリストを平坦化する最善の方法を皆さんはどうお考えでしょうか?

このようなリストをネストしたリスト内包で平坦化しようとすると、次のようになります。

[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 オブジェクトを作成します。

結論 :

この質問に投稿してくれた皆さん、ありがとうございました。 以下は、私が学んだことをまとめたものです。 また、他の人がこれらの観察に追加したり修正したりしたい場合に備えて、これをコミュニティWikiにしています。

私のオリジナルのreduce文は冗長なので、このように書いた方がよいでしょう。

>>> reduce(list.__add__, (list(mi) for mi in list_of_menuitems))

これは、ネストされたリスト内包の正しい構文です(Brilliant summary dF !):

>>> [image for mi in list_of_menuitems for image in mi]

しかし、これらの方法は、どちらも itertools.chain :

>>> from itertools import chain
>>> list(chain(*list_of_menuitems))

また、@cdleary が指摘しているように、 * 演算子マジックを避けるためには、おそらく chain.from_iterable というように。

>>> chain = itertools.chain.from_iterable([[1,2],[3],[5,89],[],[6]])
>>> print(list(chain))
>>> [1, 2, 3, 5, 89, 6]

解決方法は?

もし、データ構造の平坦化されたバージョンを反復処理したいだけで、インデックス可能なシーケンスは必要ないのであれば、次のことを検討してみてください。 itertools.chainと会社 .

>>> list_of_menuitems = [['image00', 'image01'], ['image10'], []]
>>> import itertools
>>> chain = itertools.chain(*list_of_menuitems)
>>> print(list(chain))
['image00', 'image01', 'image10']

これは反復可能なものであれば何でも動作します。 QuerySet を使用しているようですね。

編集する なぜなら、reduceは拡張されるリストに項目をコピーするのと同じオーバーヘッドが発生するからです。 chain を実行した場合のみ、この(同じ)オーバーヘッドが発生します。 list(chain) を最後に記述します。

メタ編集です。 実際には、オリジナルをテンポラリで拡張する際に作成したテンポラリリストを捨てるので、質問の解決案よりもオーバーヘッドが少なくなります。

編集する として J.F.セバスチャンのコメント itertools.chain.from_iterable は解凍を避けるので、それを使って * のマジックがありますが timeitアプリ は、パフォーマンスの差はごくわずかであることがわかります。