Daftar pemahaman pada daftar bersarang?

219

Saya punya daftar bersarang ini:

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']]

Sekarang, yang ingin saya lakukan adalah mengonversi setiap elemen dalam daftar menjadi float. Solusi saya adalah ini:

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

Tetapi dapatkah ini dilakukan dengan menggunakan pemahaman daftar bersarang, bukan?

apa yang saya lakukan adalah:

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

Tapi kemudian hasilnya adalah sekelompok 100 dengan jumlah 2400.

solusi apa pun, sebuah penjelasan akan sangat dihargai. Terima kasih!

Boy Pasmo
sumber
15
Apakah Anda juga ingin meratakan daftar Anda?
Greg Hewgill
@GregHewgill: OP tidak membalas, tetapi berdasarkan jawaban yang mereka terima, tampaknya mereka ingin tetap bersarang.
smci

Jawaban:

317

Inilah cara Anda melakukan ini dengan pemahaman daftar bersarang:

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

Ini akan memberi Anda daftar daftar, mirip dengan apa yang Anda mulai dengan kecuali dengan float, bukan string. Jika Anda menginginkan satu daftar datar maka Anda akan menggunakannya [float(y) for x in l for y in x].

Andrew Clark
sumber
190

Berikut ini cara mengkonversi nested for loop ke nested listrehension:

masukkan deskripsi gambar di sini

Berikut adalah cara kerja pemahaman daftar bersarang:

            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]

Untuk kasus Anda, itu akan menjadi seperti ini.

In [4]: new_list = [float(y) for x in l for y in x]
Rahul
sumber
21
Sangat berguna! Jelaskan bahwa loop (atas ke bawah) dipesan dari kiri ke kanan dalam generator. Ini tidak jelas karena di (f(x) for x in l)tempat baris kedua for-loop ekuivalen di sebelah kiri.
user48956
Ini sepertinya satu-satunya penjelasan yang benar-benar tepat untuk saya, terima kasih!
Douglas Plumley
48
>>> 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]
falsetru
sumber
42

Tidak yakin apa output yang Anda inginkan, tetapi jika Anda menggunakan pemahaman daftar, urutan mengikuti urutan loop bersarang, yang Anda miliki mundur. Jadi saya mendapatkan apa yang saya pikir Anda inginkan:

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

Prinsipnya adalah: gunakan urutan yang sama yang akan Anda gunakan dalam menuliskannya sebagai bersarang untuk loop.

Harry Binswanger
sumber
ini harus menjadi jawabannya, karena beberapa kali kita tidak ingin mengurung braket iteratool
zinking
1
ini mungkin bukan jawaban yang benar karena menghasilkan daftar yang tidak bersarang, tetapi inilah yang saya cari, terutama asasnya . Terima kasih!
Rodrigo E. Principe
4

Karena saya sedikit terlambat di sini tetapi saya ingin berbagi bagaimana sebenarnya pemahaman daftar bekerja terutama pemahaman daftar bersarang:

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

sebenarnya sama dengan:

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

Dan sekarang daftar pemahaman bersarang:

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

sama dengan;

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)

keluaran:

[[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]]
Aaditya Ura
sumber
3

Jika Anda tidak menyukai pemahaman daftar bersarang, Anda dapat menggunakan fungsi peta juga,

>>> 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]]
narayan
sumber
Kode Anda menghasilkan objek peta alih-alih daftar: >>> float_l = [map(float, nested_list) for nested_list in l] [[<map at 0x47be9b0>], [<map at 0x47be2e8>], [<map at 0x47be4a8>], [<map at 0x47beeb8>], [<map at 0x484b048>], [<map at 0x484b0b8>]] tetapi menambahkan panggilan tambahan ke daftar berfungsi seperti yang diharapkan: >>> float_l = [list(map(float, nested_list)) for nested_list in l]
pixelperfect
@pixelperfect yang disebabkan oleh ( misinformed ..) perubahan python3untuk mengembalikan generator keluar dari pemahaman.
javadba
3

Saya memiliki masalah yang sama untuk dipecahkan sehingga saya menemukan pertanyaan ini. Saya melakukan perbandingan kinerja jawaban Andrew Clark dan narayan yang ingin saya bagikan.

Perbedaan utama antara dua jawaban adalah bagaimana mereka mengulangi daftar dalam. Salah satunya menggunakan peta builtin , sementara yang lain menggunakan daftar pemahaman. Fungsi peta memiliki sedikit keunggulan kinerja untuk pemahaman daftar yang setara jika tidak memerlukan penggunaan lambdas . Jadi dalam konteks pertanyaan ini mapharus melakukan sedikit lebih baik daripada pemahaman daftar.

Mari kita lakukan tolok ukur kinerja untuk melihat apakah itu benar. Saya menggunakan python versi 3.5.0 untuk melakukan semua tes ini. Pada set pertama pengujian saya ingin mempertahankan elemen per daftar menjadi 10 dan memvariasikan jumlah daftar dari 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

masukkan deskripsi gambar di sini

Pada set tes berikutnya saya ingin meningkatkan jumlah elemen per daftar menjadi 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

masukkan deskripsi gambar di sini

Mari kita mengambil langkah berani dan memodifikasi jumlah elemen dalam daftar menjadi 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

masukkan deskripsi gambar di sini

Dari tes ini kita dapat menyimpulkan bahwa mapmemiliki manfaat kinerja melebihi pemahaman daftar dalam hal ini. Ini juga berlaku jika Anda mencoba melakukan cast ke salah satu intatau str. Untuk sejumlah kecil daftar dengan lebih sedikit elemen per daftar, perbedaannya dapat diabaikan. Untuk daftar yang lebih besar dengan lebih banyak elemen per daftar orang mungkin ingin menggunakan mapalih-alih pemahaman daftar, tetapi itu benar-benar tergantung pada kebutuhan aplikasi.

Namun saya pribadi menemukan pemahaman daftar lebih mudah dibaca dan idiomatis daripada map. Ini adalah standar de-facto dalam python. Biasanya orang lebih mahir dan nyaman (khususnya pemula) dalam menggunakan pemahaman daftar daripada map.

Sohaib Farooqi
sumber
2

Ya, Anda bisa melakukannya dengan kode seperti itu:

l = [[float(y) for y in x] for x in l]
Pemenang
sumber
[float(y) for y in x for x in l]ini akan menghasilkan sekelompok 100-an dengan jumlah 2400.
Boy Pasmo
2

Masalah ini dapat diselesaikan tanpa menggunakan untuk loop. Kode baris tunggal akan cukup untuk ini. Menggunakan Nested Map dengan fungsi lambda juga akan berfungsi di sini.

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)

Dan Daftar Keluaran adalah sebagai berikut:

[[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]]
Aakash Goel
sumber
1
Apakah lambdas memiliki manfaat kinerja lebih dari mengatakan solusi @Andrew Clark atau Harry Binswanger (pemahaman daftar vanilla yang lebih)? Karena lambdas sepertinya lebih sulit dibaca.
StefanJCollier
0

Cara terbaik untuk melakukan ini menurut saya adalah dengan menggunakan itertoolspaket python .

>>>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]
Thomasillo
sumber
0

Ya, Anda dapat melakukan hal berikut.

[[float(y) for y in x] for x in l]
pengguna1142317
sumber
-2
    deck = [] 
    for rank in ranks:
        for suit in suits:
            deck.append(('%s%s')%(rank, suit))

Ini dapat dicapai dengan menggunakan pemahaman daftar:

[deck.append((rank,suit)) for suit in suits for rank in ranks ]
ADITYA KUMAR
sumber
1
Tampaknya ini tidak menjawab pertanyaan di atas sama sekali. Harap dicatat bahwa segala sesuatu yang diposting sebagai jawaban harus merupakan upaya untuk menjawab pertanyaan yang diposkan.
Baum mit Augen
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda. Tolong juga cobalah untuk tidak membuat kerumunan kode Anda dengan komentar penjelasan, ini mengurangi keterbacaan kode dan penjelasan!
Filnor
Disatukan untuk loop menggunakan daftar pemahaman,
ADITYA KUMAR
1
Ok, ternyata, ini adalah upaya untuk menjawab pertanyaan. Namun, ini tampaknya tentang skenario yang sama sekali berbeda dari di OP, Anda bahkan tidak berurusan dengan daftar bersarang sebagai input, dan bahkan jika Anda mengubah saran Anda adalah apa yang sudah dicoba OP. Juga, saya tidak melihat bagaimana contoh tentang kartu membantu ketika pertanyaannya adalah tentang mengubah string menjadi float.
Baum mit Augen