2016-10-31 1 views
1

Ich entschuldige mich für diese triviale Frage, aber ich kann keine Lösung finden. Ich brauche die folgende Liste zu erstellen:Wie schreibe ich ein Listenverständnis, ohne die Auswertung einer Funktion zu wiederholen?

for i in x: 
    if(f(i) < g(i)): 
     my_list.append(f(i)*g(i)) 

aber ich weiß nicht, wie es mit der Liste Verständnis zu tun, ohne die Berechnung der Funktionen f() und g() zu wiederholen. Ich möchte es vermeiden, weil sie rechenintensiv sind. So möchte ich nicht so etwas wie:

[f(i)*g(i) for i in x if f(i) < g(i)] 

weil f(i) und g(i) berechnet zweimal bei jeder Iteration. Ich habe mich gefragt, ob es einen Weg gibt, irgendwo die Nummern f(i) und g(i) zu "speichern" und sie innerhalb des Listenverständnisses abzurufen.

+1

um ... sehr einfach ... etwas Variablen das Ergebnis von 'g (i) speichern' und 'f (i)'? –

+0

Nun, ich möchte auch sagen, dass ich keine andere for-Schleife für die Erstellung einer Liste verwenden möchte, die f (i) und g (i) enthält, weil x sehr groß ist (daher würde diese Lösung sehr zeitaufwendig sein) – user2983638

+0

Sie müssen keine zusätzliche Liste erstellen. Sieh meine Antwort. Es ist nur so, dass Sie Ihre Zwischenwerte nicht wegwerfen müssen –

Antwort

3

Sie die Werte der Anrufe in einer for Schleife Ziel speichern können, wenn Sie eine iterable erstellen (wie ein Tupel oder eine Liste) mit nur ein Element darin; dass ein Element wäre ein Tupel mit dem (f(i), g(i)) Ergebnis herer sein:

res = [fi * gi for i in x for fi, gi in [(f(i), g(i))] if fi < gi] 

Dies ist jedoch nicht recht und nicht sehr gut lesbar.

Sie würden viel besser eine tatsächliche for Schleife für diese Verwendung:

res = [] 
for i in x: 
    fi, gi = f(i), g(i) 
    if fi < gi: 
     res.append(fi * gi) 

Eine weitere Option ist ein Zwischen Generator Ausdruck zu erzeugen, die f(i) und g(i) berechnet, verwendet dann die Ausgabe in einer Liste Verständnis:

intermediate = ((f(i), g(i)) for i in x) 
res = [fi * gi for fi, gi in intermediate if fi < gi] 
+0

Ich denke, Sie haben ein zusätzliches Ein-Element-Tupel drin. – user2357112

+0

Ich stimme von ganzem Herzen dem "nicht hübschen" Teil zu. –

+0

@ user2357112: Es gibt genau ein Element im äußeren Tupel, ein anderes Tupel mit den 'f (i)' und 'g (i)' Ergebnissen. Die zusätzlichen Anrufklammern verwirren die Dinge etwas; eine Liste ist wahrscheinlich besser. –

1

um ... sehr einfach ... was ist mit Variablen, um das Ergebnis von g(i) und f(i) zu speichern?

statt

for i in x: 
    if(f(i) < g(i)): 
     my_list.append(f(i)*g(i)) 

etwas tun, wie

for i in x: 
    a = f(i) 
    b = g(i) 
    if a < b: 
     my_list.append(a*b) 
+0

Ok, aber ist es möglich, Ihren letzten Code in Listenverstehen zu schreiben? – user2983638

+0

ja, siehe martijns [antwort] (http://stackoverflow.com/a/40351410/4433386); aber es ist nicht intuitiv zu tun. Wenn Sie erneut einen Zwischenwert benötigen, speichern Sie ihn in einer Variablen. Zeitraum. –

1

können Sie vermeiden append wie folgt verwendet:

def func(x): 
    for i in x: 
     a = f(i) 
     b = g(i) 
     if a < b: 
      yield a*b 

my_list = list(func(x)) 
+0

Danke, ich werde auch diese Lösung versuchen. Im Grunde versuche ich, meinen Code zu beschleunigen, also könnte 'Ausbeute' nützlich sein. – user2983638

1

Betrachten

[ fi * gi for fi, gi in zip(map(f, x), map(g, x)) if fi < gi ] 
Verwandte Themen