私が見つけた最も速い方法は、空の配列から始めてそれを拡張することです:
In [1]: a = [['abc', 'def'], ['ghi'],['xzy']]
In [2]: result = []
In [3]: extend = result.extend
In [4]: for l in a:
...: extend(l)
...:
In [5]: result
Out[5]: ['abc', 'def', 'ghi', 'xzy']
これは、Alex Martelli の試みの例の 2 倍以上高速です: Making a flat list out of list of list in Python
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 86.3 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'b = []' 'extend = b.extend' 'for sub in l:' ' extend(sub)'
10000 loops, best of 3: 36.6 usec per loop
これを思いついたのは、バックグラウンドでextendがリストに適切な量のメモリを割り当て、おそらくいくつかの低レベルコードを使用してアイテムを移動するという予感があったためです。これが本当かどうかはわかりませんが、誰が気にしても、それはより高速です。
ちなみに、これは線形の高速化のみです。
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]' 'b = []' 'extend = b.extend' 'for sub in l:' ' extend(sub)'
1000000 loops, best of 3: 0.844 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]' '[item for sublist in l for item in sublist]'
1000000 loops, best of 3: 1.56 usec per loop
を使用することもできますがmap(results.extend, a)
、これは独自の Nones リストを作成しているため遅くなります。
また、関数型プログラミングを使用しない利点もいくつかあります。すなわち
- 空のリストを作成する代わりに、既存のリストを拡張できます。
- 数分後、数日後、さらには数か月後でも、一目でコードを理解できます。
ところで、おそらくリスト内包表記は避けるのが最善でしょう。小さなリスト内包表記はそれほど悪くはありませんが、一般的に、リスト内包表記は入力の手間をあまり省きませんが、多くの場合、理解するのが難しく、変更やリファクタリングが非常に困難です (3 レベルのリスト内包表記を見たことがありますか?)。Google のコーディング ガイドラインでは、単純な場合を除き、それらを使用しないことを推奨しています。私の意見では、それらは「使い捨て」コード、つまり作成者が可読性を気にしないコード、または将来のメンテナンスを必要としないことが知られているコードでのみ有用であるというものです。
同じことを書く次の 2 つの方法を比較します。
result = [item for sublist in l for item in sublist]
これとともに:
result = []
for sublist in l:
for item in sublist:
result.append(item)
YMMV ですが、最初の 1 つで足が止まり、考えなければなりませんでした。2 番目の例では、入れ子がインデントから明らかになっています。