web-dev-qa-db-ja.com

入れ子リストのリスト内包表記

私はこのネストしたリストを持っています:

l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

さて、私がやりたいことはリストの各要素をfloatに変換することです。私の解決策はこれです:

newList = []
for x in l:
  for y in x:
    newList.append(float(y))

しかし、これはネストしたリストの内包表記を使用して実行できますか?

私がやったことは:

[float(y) for y in x for x in l]

しかし、結果は2400の合計で100の束です。

どのような解決策でも、説明をいただければ幸いです。ありがとうございます。

184
Boy Pasmo

これはネストしたリストの内包表記を使ってこれを行う方法です。

[[float(y) for y in x] for x in l]

これは、文字列ではなく浮動小数点数を使用することを除いて、あなたが始めたものに似たリストのリストを与えるでしょう。 1つのフラットリストが必要な場合は[float(y) for x in l for y in x]を使用します。

270
Andrew Clark

これは、入れ子になったforループを入れ子にされたリスト内包表記に変換する方法です。

enter image description here

これがネストしたリストの内包表記の仕組みです。

            l a b c d e f
            ↓ ↓ ↓ ↓ ↓ ↓ ↓
In [1]: l = [ [ [ [ [ [ 1 ] ] ] ] ] ]
In [2]: for a in l:
   ...:     for b in a:
   ...:         for c in b:
   ...:             for d in c:
   ...:                 for e in d:
   ...:                     for f in e:
   ...:                         print(float(f))
   ...:                         
1.0

In [3]: [float(f)
         for a in l
   ...:     for b in a
   ...:         for c in b
   ...:             for d in c
   ...:                 for e in d
   ...:                     for f in e]
Out[3]: [1.0]

#Which can be written in single line as
In [4]: [float(f) for a in l for b in a for c in b for d in c for e in d for f in e]
Out[4]: [1.0]
132
Rahul
>>> l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
>>> new_list = [float(x) for xs in l for x in xs]
>>> new_list
[40.0, 20.0, 10.0, 30.0, 20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0, 30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]
44
falsetru

目的の出力が何であるかはわかりませんが、リスト内包表記を使用している場合、順序は入れ子になったループの順序に従います。だから私はあなたが望むと思うものを手に入れました:

[float(y) for x in l for y in x]

原則は次のとおりです。ループを入れ子にしたものと同じ順序で書き出します。

31

私は少し遅れているので、リスト内包表記、特にネスト化されたリスト内包表記が実際にどのように機能するかを共有したいと思いました。

   New_list= [[float(y) for x in l]

実際には同じです:

New_list=[]
for x in l:
    New_list.append(x)

そして今ネストされたリスト内包表記:

[[float(y) for y in x] for x in l]

と同じです。

new_list=[]
for x in l:
    sub_list=[]
    for y in x:
        sub_list.append(float(y))

    new_list.append(sub_list)

print(new_list)

出力:

[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]
4
Aaditya Ura

私は解決するために同様の問題を抱えていたので、私はこの質問に出くわしました。 Andrew Clarkとnarayanの答えを性能比較しました。

2つの答えの主な違いは、それらが内部リストに対してどのように反復するかです。そのうちの一つは組み込みの map を使い、他のものはリスト内包表記を使っています。 もしマップ関数がlambdasの使用を必要としないのであれば、同等のリスト内包表記よりもMap関数の方がパフォーマンス上わずかに有利です そのため、この質問の文脈では、mapはリスト内包表記よりもわずかに優れているはずです。

それが実際に本当であるかどうか見るためにパフォーマンスベンチマークをすることを許可しなさい。私はこれらすべてのテストを実行するのにpythonバージョン3.5.0を使いました。最初の一連のテストでは、リストあたりの要素数を10にし、リスト数をから変えたいと思います。10 -100,000

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10]"
>>> 100000 loops, best of 3: 15.2 usec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10]"
>>> 10000 loops, best of 3: 19.6 usec per loop 

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100]"
>>> 100000 loops, best of 3: 15.2 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100]"
>>> 10000 loops, best of 3: 19.6 usec per loop 

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*1000]"
>>> 1000 loops, best of 3: 1.43 msec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*1000]"
>>> 100 loops, best of 3: 1.91 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10000]"
>>> 100 loops, best of 3: 13.6 msec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10000]"
>>> 10 loops, best of 3: 19.1 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 164 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 216 msec per loop

enter image description here

次の一連のテストでは、リストあたりの要素数を100に増やします。

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 110 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 151 usec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.11 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.5 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 11.2 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 16.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 134 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 171 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.32 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.7 sec per loop

enter image description here

勇敢な一歩を踏み出して、リストの要素数を1000に変更しましょう。

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 800 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 1.16 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 8.26 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 11.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 83.8 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 118 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 868 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 1.23 sec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 9.2 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 12.7 sec per loop

enter image description here

これらのテストから、この場合はmapがリスト内包表記よりもパフォーマンス上の利点があると結論付けることができます。これはintまたはstrにキャストしようとしている場合にも当てはまります。リストあたりの要素数が少ないリストの数が少ない場合、その違いはごくわずかです。リストあたりの要素数が多い大きなリストの場合は、リスト内包表記の代わりにmapを使用することをお勧めしますが、アプリケーションのニーズに完全に依存します。

しかし、私は個人的にはリストの内包表記がmapより読みやすく慣用的であると感じています。これはpythonの事実上の標準です。通常、人々はmapよりもリスト内包表記を使うことに熟達していて快適です(特に初心者)。

3
bro-grammer

入れ子になったリスト内包表記が気に入らない場合は、 map 関数も使用できます。

>>> from pprint import pprint

>>> l = l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] 

>>> pprint(l)
[['40', '20', '10', '30'],
['20', '20', '20', '20', '20', '30', '20'],
['30', '20', '30', '50', '10', '30', '20', '20', '20'],
['100', '100'],
['100', '100', '100', '100', '100'],
['100', '100', '100', '100']]

>>> float_l = [map(float, nested_list) for nested_list in l]

>>> pprint(float_l)
[[40.0, 20.0, 10.0, 30.0],
[20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0],
[30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0],
[100.0, 100.0],
[100.0, 100.0, 100.0, 100.0, 100.0],
[100.0, 100.0, 100.0, 100.0]]
3
narayan

この問題はforループを使用せずに解決できます。これには単一行コードで十分です。ラムダ関数で入れ子になった地図を使うことはここでも働きます。

l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

map(lambda x:map(lambda y:float(y),x),l)

そして出力リストは次のようになります。

[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]
2
Aakash Goel

はい、あなたはそのようなコードでそれをすることができます:

l = [[float(y) for y in x] for x in l]
2
Victor

はい、できます。

[[float(y) for y in x] for x in l]
0
user1142317

私の考えではこれを行うための最良の方法はpythonのitertoolsパッケージを使うことです。

>>>import itertools
>>>l1 = [1,2,3]
>>>l2 = [10,20,30]
>>>[l*2 for l in itertools.chain(*[l1,l2])]
[2, 4, 6, 20, 40, 60]
0
Thomasillo