wake-up-neo.net

Listenverständnis auf einer verschachtelten Liste?

Ich habe diese verschachtelte Liste:

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

Nun möchte ich jedes Element in einer Liste in Float konvertieren. Meine Lösung lautet:

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

Aber kann dies mit Hilfe des Verständnisses verschachtelter Listen geschehen, oder?

was ich getan habe ist:

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

Aber dann ist das Ergebnis ein Haufen von 100 mit der Summe von 2400.

für jede Lösung wäre eine Erklärung sehr dankbar. Vielen Dank!

189
Boy Pasmo

So würden Sie dies mit einem verschachtelten Listenverständnis tun:

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

Dies würde Ihnen eine Liste von Listen geben, ähnlich wie Sie es mit Ausnahme von Floats anstelle von Strings begonnen haben. Wenn Sie eine flache Liste wünschen, würden Sie [float(y) for x in l for y in x] verwenden.

279
Andrew Clark

So konvertieren Sie verschachtelte for-Schleifen in verschachtelte Listen:

enter image description here

So funktioniert das Verständnis verschachtelter Listen:

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

Sie sind sich nicht sicher, was Ihre gewünschte Ausgabe ist, aber wenn Sie das Listenverständnis verwenden, folgt die Reihenfolge der verschachtelten Schleifen, die Sie rückwärts haben. Also habe ich das bekommen, womit ich denke, dass Sie wollen:

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

Das Prinzip ist: Verwenden Sie dieselbe Reihenfolge, in der Sie es als verschachtelt für Schleifen ausschreiben würden.

31

Da ich mich hier etwas verspätet habe, wollte ich aber mitteilen, wie das Listenverständnis tatsächlich funktioniert, insbesondere das verschachtelte Listenverständnis:

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

ist eigentlich dasselbe wie:

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

Und jetzt verschachteltes Listenverständnis:

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

ist dasselbe wie;

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)

ausgabe:

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

Ich hatte ein ähnliches Problem zu lösen und bin auf diese Frage gestoßen. Ich habe einen Leistungsvergleich von Andrew Clarks und Narayans Antwort durchgeführt, den ich gerne teilen möchte.

Der Hauptunterschied zwischen zwei Antworten besteht darin, wie sie über innere Listen iterieren. Einer von ihnen benutzt builtin map , während der andere das Listenverständnis benutzt. Die Kartenfunktion hat einen leichten Leistungsvorteil gegenüber dem entsprechenden Listenverständnis, wenn die Verwendung von Lambdas nicht erforderlich ist. . Im Zusammenhang mit dieser Frage sollte map etwas besser abschneiden als das Listenverständnis.

Machen wir einen Performance-Benchmark, um zu sehen, ob er tatsächlich wahr ist. Ich habe python version 3.5.0 verwendet, um alle diese Tests durchzuführen. In der ersten Testreihe möchte ich die Anzahl der Elemente pro Liste auf 10 und variieren Sie die Anzahl der Listen von 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

In den nächsten Tests möchte ich die Anzahl der Elemente pro Liste auf 100 erhöhen.

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

Machen wir einen mutigen Schritt und ändern Sie die Anzahl der Elemente in Listen auf 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

Aus diesem Test können wir schließen, dass map in diesem Fall einen Leistungsvorteil gegenüber dem Listenverständnis hat. Dies gilt auch, wenn Sie versuchen, eine Umwandlung in int oder str vorzunehmen. Für eine kleine Anzahl von Listen mit weniger Elementen pro Liste ist der Unterschied vernachlässigbar. Bei größeren Listen mit mehr Elementen pro Liste wird möglicherweise map anstelle des Listenverständnisses verwendet, dies hängt jedoch vollständig von den Anwendungsanforderungen ab.

Ich persönlich finde das Listenverständnis jedoch lesbarer und idiomatischer als map. Es ist ein De-facto-Standard in Python. Normalerweise beherrschen die Leute das Listenverständnis besser und sicherer (besonders Anfänger) als map.

3
Sohaib Farooqi

Wenn Sie verschachtelte Listen nicht mögen, können Sie auch die Funktion map verwenden.

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

Dieses Problem kann ohne die Verwendung von for loop gelöst werden. Einzeiliger Code ist hierfür ausreichend. Die Verwendung von verschachtelter Karte mit Lambda-Funktion funktioniert auch hier.

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)

Und Output List wäre wie folgt:

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

Ja, Sie können es mit einem solchen Code tun:

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

Ja, Sie können Folgendes tun.

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

Meiner Meinung nach ist der beste Weg, dies zu tun, das itertools -Paket von Python zu verwenden.

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