Sie einen Ausdruck verwenden können verschachtelte Generator anwenden kann nur einmal um die Funktion aufzurufen:
[(x, fx) for (x, fx) in ((x, f(x)) for x in list_x) if fx == cond(x)]
Der Generatorausdruck wird im Lockstep iteriert, um die (x, fx)
Tupel für das Listenverständnis zu erzeugen.
Wenn Sie diese leichter auf den Leser zu finden, können Sie zuerst den Generator Ausdruck in einen separaten Namen aufzuschlüsseln:
mapped_x = ((x, f(x)) for x in list_x)
filtered_x = [(x, fx) for (x, fx) in mapped_x if fx == cond(x)]
Um diesen Punkt erneut durchlaufen: der Generator Ausdruck wird träge ausgeführt; Die Schleife for
im Ausdruck wird Schritt für Schritt für jeden Schritt in der Schleife for ... in mapped_x
vorgerückt.
Demo:
>>> list_x = range(5)
>>> f = lambda x: print('f({!r})'.format(x)) or (x ** 2 - 1)
>>> cond = lambda x: print('cond({!r})'.format(x)) or x % 2 == 0
>>> mapped_x = ((x, f(x)) for x in list_x)
>>> [(x, fx) for (x, fx) in mapped_x if fx == cond(x)]
f(0)
cond(0)
f(1)
cond(1)
f(2)
cond(2)
f(3)
cond(3)
f(4)
cond(4)
[(1, 0)]
Beachten Sie, wie f(x)
nur einmal aufgerufen wird, und der Zustand sofort überprüft wird.
Wie effizient das ist, hängt davon ab, wie teuer der f(x)
Anruf ist; Ein Generatorausdruck wird als separater Funktionsrahmen ausgeführt, und der Interpreter wechselt zwischen den beiden Rahmen (die Schleife für das Listenverständnis ist ebenfalls ein Rahmenobjekt). Wenn f(x)
eine Python-Funktion ist, haben Sie bereits gewonnen, da Sie nun die Anzahl der erstellten Funktionsrahmenobjekte halbiert haben (jeder Aufruf von f(x)
erstellt auch ein Rahmenobjekt und das Erstellen dieser Rahmen ist relativ kostspielig). Für C-Funktionen sollten Sie einige Testläufe mit der timeit
module erstellen, um zu sehen, was für Ihre erwartete Listengröße schneller ist.
wenn Sie 'verwenden map' warum nicht' filter' auch mit? ... – Julien
Sie sind willkommen Ihre Version von Antwort –
Hinweis zu liefern, dass eine 'lambda' mit diesem deutlich verlangsamt (Erstellen und knallend das Funktionsrahmenobjekt N mal für eine Listenlänge N). –