Angenommen, ich habe eine Liste mit einer großen Anzahl von Elementen.
l = [ 1, 4, 6, 30, 2, ... ]
Ich möchte die Anzahl der Elemente aus dieser Liste abrufen, wobei ein Element bestimmte Bedingungen erfüllen sollte. Mein erster Gedanke war:
count = len([i for i in l if my_condition(l)])
Wenn die gefilterte Liste my_condition () auch eine große Anzahl von Elementen enthält, ist das Erstellen einer neuen Liste für gefilterte Ergebnisse meiner Meinung nach nur Speicherverschwendung. Aus Effizienzgründen kann der obige Aufruf meiner Meinung nach nicht besser sein als:
count = 0
for i in l:
if my_condition(l):
count += 1
Gibt es eine funktionale Möglichkeit, um die Anzahl der Elemente zu ermitteln, die bestimmte Bedingungen erfüllen, ohne eine temporäre Liste zu erstellen?
Danke im Voraus.
Antworten:
Sie können einen Generatorausdruck verwenden :
>>> l = [1, 3, 7, 2, 6, 8, 10] >>> sum(1 for i in l if i % 4 == 3) 2
oder auch
>>> sum(i % 4 == 3 for i in l) 2
das nutzt die Tatsache, dass
int(True) == 1
.Alternativ können Sie
itertools.imap
(Python 2) oder einfachmap
(Python 3) verwenden:>>> def my_condition(x): ... return x % 4 == 3 ... >>> sum(map(my_condition, l)) 2
quelle
start
standardmäßig 0, also ist die erste AdditionTrue + 0
, nein?int(True)
ist.int("1") == 1
auch, aber das heißt nicht, dass du es kannst"1" + 0
. Was zählt ist, wie Python bewertetinteger + True
oderinteger + False
.bool
es sich um eine Unterklasse von handeltint
und Sie einfach Bools und Ints hinzufügen können (mitTrue
einem Wert von 1 undFalse
einem Wert von 0).int(True) == 1
, aber Ihr Punkt, derint("1") == 1
beweist, dass eine Abkürzung auf diese Weise Dinge implizieren kann, die nicht wahr sind.Sie möchten hier eher ein Generatorverständnis als eine Liste.
Zum Beispiel,
l = [1, 4, 6, 7, 30, 2] def my_condition(x): return x > 5 and x < 20 print sum(1 for x in l if my_condition(x)) # -> 2 print sum(1 for x in range(1000000) if my_condition(x)) # -> 14
Oder verwenden Sie
itertools.imap
(obwohl ich denke, dass die expliziten Listen- und Generatorausdrücke etwas pythonischer aussehen).Beachten Sie, dass Sie, obwohl dies aus dem
sum
Beispiel nicht ersichtlich ist, das Generatorverständnis gut zusammenstellen können. Zum Beispiel,inputs = xrange(1000000) # In Python 3 and above, use range instead of xrange odds = (x for x in inputs if x % 2) # Pick odd numbers sq_inc = (x**2 + 1 for x in odds) # Square and add one print sum(x/2 for x in sq_inc) # Actually evaluate each one # -> 83333333333500000
Das Coole an dieser Technik ist, dass Sie konzeptionell separate Schritte im Code angeben können, ohne die Auswertung und Speicherung im Speicher zu erzwingen, bis das Endergebnis ausgewertet wird.
quelle
Dies kann auch mit erfolgen,
reduce
wenn Sie eine funktionale Programmierung bevorzugenreduce(lambda count, i: count + my_condition(i), l, 0)
Auf diese Weise machen Sie nur 1 Durchgang und es wird keine Zwischenliste generiert.
quelle
Sie könnten so etwas tun wie:
l = [1,2,3,4,5,..] count = sum(1 for i in l if my_condition(i))
Dies fügt nur 1 für jedes Element hinzu, das die Bedingung erfüllt.
quelle
from itertools import imap sum(imap(my_condition, l))
quelle
imap
ist mit aktuellem Python nicht verfügbar.