Einzeiliges Listenverständnis: If-else-Varianten

178

Es geht mehr um die Syntax des Python-Listenverständnisses. Ich habe ein Listenverständnis, das eine Liste ungerader Zahlen eines bestimmten Bereichs erzeugt:

[x for x in range(1, 10) if x % 2]

Dies macht einen Filter - ich habe eine Quellenliste, in der ich gerade Zahlen entferne ( if x % 2). Ich würde hier gerne so etwas wie Wenn-Dann-Sonst verwenden. Der folgende Code schlägt fehl:

>>> [x for x in range(1, 10) if x % 2 else x * 100]
  File "<stdin>", line 1
    [x for x in range(1, 10) if x % 2 else x * 100]
                                         ^
SyntaxError: invalid syntax

Es gibt einen Python-Ausdruck wie if-else:

1 if 0 is 0 else 3

Wie verwende ich es in einem Listenverständnis?

Ducin
quelle
1
Wenn Sie wissen, was es wert ist, haben Sie ein "Listenverständnis", keinen Generator. Die ultimative Syntax ist dieselbe, außer dass Generatoren ()anstelle von verwenden [].
mgilson
2
Es dauerte eine Weile , um zu bekommen , warum if x % 2 eliminiert gerade Zahlen (statt sie zu halten) - es ist da , wenn xsogar die x % 2Expression zu 0, was wiederum wertet auf False, während jede intAusnahme 0auswertet zu True.

Antworten:

328

x if y else zist die Syntax für den Ausdruck, den Sie für jedes Element zurückgeben. Sie brauchen also:

[ x if x%2 else x*100 for x in range(1, 10) ]

Die Verwirrung ergibt sich aus der Tatsache, dass Sie im ersten Beispiel einen Filter verwenden, im zweiten jedoch nicht. Im zweiten Beispiel sind Sie nur abbildet , jeden Wert zu einem anderen, einen ternären-Operator Ausdruck.

Mit einem Filter benötigen Sie:

[ EXP for x in seq if COND ]

Ohne Filter benötigen Sie:

[ EXP for x in seq ]

und in Ihrem zweiten Beispiel ist der Ausdruck ein "komplexer", der zufällig einen beinhaltet if-else.

shx2
quelle
2
Ich habe eine Frage ... [x for x in range(1, 10) if x % 2]ist die richtige Syntax. [x if x % 2 for x in range(1, 10)]- Dies ist keine [x if x%2 else x*100 for x in range(1, 10)]korrekte Syntax , aber auch hier. Woher?
Ducin
@tkoomzaaskz in Ihrem zweiten Beispiel, dies ist weder ein ternärer If-else-Operator (ohne den else) noch ein Filter (da er EXPTeil des Listenverständnisses ist)
shx2
3
@tkoomzaaskz Beachten Sie zur weiteren Verdeutlichung, dass Sie ifam Ende eine Sekunde hinzufügen können : [x if x%2 else x*100 for x in range(1, 10) if not x%3]Die erste ifist Teil des ternären Operators, die zweite ifist Teil der Listenverständnis-Syntax. Das Ganze x if x%2 else x*100ist "auf der gleichen Ebene" wie ein einfaches 2*x, es ist der Ausdruck, der auf der linken Seite des zu bewerten ist for, wenn die Filterung von if not x%3bereits stattgefunden hat.
zx81
Hallo, wäre eine einzeilige Anweisung performanter, als sie in zwei Zeilen wie for i in x:und dann in der for-Schleife zu erstellen if i == y:?
Alexis.Rolland
23
[x if x % 2 else x * 100 for x in range(1, 10) ]
lucasg
quelle
12

Sie können dies auch mit Listenverständnis tun:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A
Stefan Gruenwald
quelle
1
Sehr schön. Eine boolesche Scheibe. Danke, Sie haben mir gerade eine besser lesbare Lösung gegeben.
Sie können auch doppelt so zuweisen: A, B = [10,11] [a == 19], [1,14] [a == 20]
Stefan Gruenwald
10

Nur eine andere Lösung, hoffe es könnte jemandem gefallen:

Verwenden von: [False, True] [Expression]

>>> map(lambda x: [x*100, x][x % 2 != 0], range(1,10))
[1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
James Sapam
quelle
3

Ich konnte das tun

>>> [x if x % 2 != 0 else x * 100 for x in range(1,10)]
    [1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
anudeep
quelle