Yuvalanmış bir listede liste anlama?


219

Bu iç içe liste var:

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

Şimdi yapmak istediğim bir listedeki her öğeyi kayan duruma çevirmektir. Benim çözümüm şudur:

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

Ancak bu, iç içe liste kavrayışı kullanılarak yapılabilir, değil mi?

yaptığım şey:

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

Ama sonra sonuç 2400'ün toplamı ile 100'lerin demetidir.

herhangi bir çözüm, bir açıklama çok takdir edilecektir. Teşekkürler!


15
Listenizi de düzleştirmek mi istiyorsunuz ?
Greg Hewgill

@GregHewgill: OP cevap vermedi, ancak kabul ettikleri cevaba göre, yuvalamayı olduğu gibi tutmak istiyorlar.
smci

Yanıtlar:


318

Bunu, iç içe geçmiş liste kavrayışıyla nasıl yapacağınız aşağıda açıklanmıştır:

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

Bu, dizeler yerine şamandıralar dışında başladığınıza benzer bir liste listesi verir. Bir düz liste istiyorsanız o zaman kullanabilirsiniz [float(y) for x in l for y in x].


191

İç içe döngü için iç içe liste kavrama nasıl dönüştürülür:

resim açıklamasını buraya girin

Yuvalanmış liste kavrayışı şu şekilde çalışır:

            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]

Sizin durumunuz için böyle bir şey olacak.

In [4]: new_list = [float(y) for x in l for y in x]

21
Süper kullanışlı! Jeneratörde döngülerin (yukarıdan aşağıya) soldan sağa doğru sıralandığını netleştirir. (f(x) for x in l)Solda for-loop eşdeğerinin ikinci satırını yerleştirdiği için bu açık değildir .
user48956

Bu aslında benimle eve çarpan tek açıklama gibi görünüyor, teşekkür ederim!
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]

42

İstediğiniz çıktının ne olduğundan emin değilim, ancak liste kavrayıcı kullanıyorsanız, sıra, geriye doğru sahip olduğunuz iç içe döngülerin sırasını izler. Yani istediğini düşündüğüm şeyi aldım:

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

İlke şudur: döngüler için iç içe olarak yazarken kullandığınız sırayı kullanın.


Bu cevap olmalı, çünkü bazen iteratool köşeli ayraç istemiyoruz
01'de

1
bu, iç içe olmayan bir liste çıkardığı için doğru cevap olmayabilir, ama aradığım şey, özellikle de prensip . Teşekkürler!
Rodrigo

4

Burada biraz geç kaldığım için ama aslında liste kavrayışının özellikle iç içe liste kavrayışının nasıl çalıştığını paylaşmak istedim:

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

aslında aynı:

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

Ve şimdi iç içe liste kavrama:

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

ile aynıdır;

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)

çıktı:

[[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

Yuvalanmış liste kavrayışlarından hoşlanmıyorsanız, harita işlevini de kullanabilirsiniz,

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

Kodunuz listeler yerine harita nesneleri oluşturur: >>> 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>]] ancak listelemek için ek bir çağrı eklendiğinde beklendiği gibi çalışır: >>> float_l = [list(map(float, nested_list)) for nested_list in l]
pixelperfect

@ pixelperfect ( yanlış bilgi ..) değişiklik nedeniyle python3jeneratörleri kavrayış dışında dönmek için.
javadba

3

Çözmek için benzer bir sorunum vardı, bu yüzden bu soruya rastladım. Andrew Clark'ın ve narayan'ın cevabını paylaşmak istediğim yanıtı performans karşılaştırması yaptım.

İki cevap arasındaki temel fark, iç listeler üzerinde nasıl tekrar ettikleri. Bunlardan biri yerleşik haritayı kullanırken diğeri liste kavrayışı kullanıyor. Harita işlevi, lambdas kullanımını gerektirmiyorsa, eşdeğer liste kavrayışına göre küçük bir performans avantajına sahiptir . Dolayısıyla bu soru bağlamında mapliste kavrayışından biraz daha iyi performans göstermelidir.

Bunun doğru olup olmadığını görmek için bir performans ölçütü yapalım. Tüm bu testleri gerçekleştirmek için python 3.5.0 sürümünü kullandım. İlk test kümesinde, liste başına öğelerin 10 olmasını ve liste sayısını 10-100.000 arasında değiştirmesini istiyorum.

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

resim açıklamasını buraya girin

Bir sonraki test grubunda, liste başına öğe sayısını 100'e yükseltmek istiyorum .

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

resim açıklamasını buraya girin

Cesur bir adım atalım ve listelerdeki öğe sayısını 1000 olarak değiştirelim

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

resim açıklamasını buraya girin

Bu testten map, bu durumda liste kavrama üzerinde performans avantajı olduğu sonucuna varabiliriz . Bu, intveya öğelerinden birine yayınlamaya çalışıyorsanız da geçerlidir str. Liste başına daha az öğe içeren az sayıda liste için fark göz ardı edilebilir. Liste başına daha fazla öğeye sahip daha büyük listeler için mapliste kavrama yerine kullanmak isteyebilirsiniz , ancak bu tamamen uygulama gereksinimlerine bağlıdır.

Ancak şahsen liste kavrayışının daha okunabilir ve deyimsel olduğunu düşünüyorum map. Python'da fiili bir standarttır. Genellikle insanlar liste kavrayışlarını kullanmaktan daha yetkin ve rahattır (özellikle yeni başlayanlar) map.



2

Bu sorun loop için kullanılmadan çözülebilir. Bunun için tek satır kodu yeterli olacaktır. İç İçe Harita'yı lambda işleviyle kullanmak da burada işe yarar.

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)

Ve Çıktı Listesi aşağıdaki gibi olacaktır:

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

1
Lamdas'ın @Andrew Clark veya Harry Binswanger'ın çözümlerine göre daha fazla performans avantajı var mı? Lambdas okumak daha zor gibi.
StefanJCollier

0

Bence bunu yapmanın en iyi yolu python itertoolspaketini kullanmak .

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

Evet, aşağıdakileri yapabilirsiniz.

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

-2
    deck = [] 
    for rank in ranks:
        for suit in suits:
            deck.append(('%s%s')%(rank, suit))

Bu, liste kavrayışı kullanılarak gerçekleştirilebilir:

[deck.append((rank,suit)) for suit in suits for rank in ranks ]

1
Bu, sorunun üstte hiç ele alındığı görülmemektedir. Yanıt olarak gönderilen her şeyin, gönderildiği soruyu cevaplamaya çalışmak olduğunu lütfen unutmayın.
Baum mit Augen

Bu kod snippet'i soruyu çözebilir, ancak bir açıklama dahil olmak , yayınınızın kalitesini artırmaya yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceğini unutmayın. Lütfen kodunuzu açıklayıcı yorumlarla doldurmamaya çalışın, bu hem kodun hem de açıklamaların okunabilirliğini azaltır!
Filnor

Liste kavrama kullanarak döngü için yuvalanmış,
ADITYA KUMAR

1
Tamam, görünüşe göre, bu soruya cevap verme girişimidir. Ancak, bu OP'den tamamen farklı bir senaryo ile ilgili gibi görünüyor, giriş olarak iç içe listelerle bile ilgilenmiyorsunuz ve önerilerinizin OP'nin zaten denediği şey olduğunu değiştirseniz bile. Ayrıca, dizeleri float'a dönüştürmekle ilgili soru olduğunda kartlarla ilgili bir örneğin nasıl yardımcı olduğunu görmüyorum.
Baum mit Augen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.