252

I have a list comprehension that produces list of odd numbers of a given range:

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

That makes a filter that removes the even numbers. Instead, I'd like to use conditional logic, so that even numbers are treated differently, but still contribute to the list. I tried this code, but it fails:

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

I know that Python expressions allow a syntax like that:

1 if 0 is 0 else 3

How can I use it inside the list comprehension?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
ducin
  • 25,621
  • 41
  • 157
  • 256
  • 2
    It took me a while to get why `if x % 2` **eliminates** even numbers (instead of keeping them) — it is because when `x` is even the `x % 2` expression results in `0`, which, in turn, evaluates to `False`, while any `int` except `0` evaluates to `True`. –  Jul 18 '18 at 06:45

6 Answers6

470

x if y else z is the syntax for the expression you're returning for each element. Thus you need:

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

The confusion arises from the fact you're using a filter in the first example, but not in the second. In the second example you're only mapping each value to another, using a ternary-operator expression.

With a filter, you need:

[ EXP for x in seq if COND ]

Without a filter you need:

[ EXP for x in seq ]

and in your second example, the expression is a "complex" one, which happens to involve an if-else.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
shx2
  • 61,779
  • 13
  • 130
  • 153
  • 2
    I've got one question... `[x for x in range(1, 10) if x % 2]` is correct syntax. `[x if x % 2 for x in range(1, 10)]` - this is not, but `[x if x%2 else x*100 for x in range(1, 10)]` is again, correct syntax. How come? – ducin Jun 26 '13 at 13:26
  • @tkoomzaaskz in your second example, this is neither a ternary-if-else operator (missing the `else`), nor a filter (since it is on the `EXP` part of the list comprehension) – shx2 May 08 '15 at 10:29
  • 3
    @tkoomzaaskz To further clarify, note that you can add a second `if` at the end: `[x if x%2 else x*100 for x in range(1, 10) if not x%3]` The first `if` is part of the ternary operator, the second `if` is part of the list comprehension syntax. The whole `x if x%2 else x*100` is "on the same level" as a simple `2*x`, it's the expression to evaluate on the left side of the `for`, when the filtering of `if not x%3` has already taken place. – zx81 Jul 01 '15 at 03:14
  • Hello, would a one-line statement be more performant than making it on two lines like `for i in x:` and then in the for loop `if i == y:` ? – Alexis.Rolland Jul 18 '18 at 06:29
30
[x if x % 2 else x * 100 for x in range(1, 10) ]
lucasg
  • 10,734
  • 4
  • 35
  • 57
19

You can do that with list comprehension too:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
Stefan Gruenwald
  • 2,582
  • 24
  • 30
15

Just another solution, hope some one may like it :

Using: [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
  • 16,036
  • 12
  • 50
  • 73
4

#how you can squre a list of an array of negative and positive values

my_list=[-2,-3,0,1,5]
squred_values=[]
  

squred_values=[-i**2 if i<0 else i**2 for i in my_list]

#or

for i in my_list:
    if i<0:
        squred_values.append( -i**2)`enter code here`
    else:
        squred_values.append( i**2) 
PM 77-1
  • 12,933
  • 21
  • 68
  • 111
Mido
  • 41
  • 4
0

two for in one list comprehension

ex = [['obi', 'is', '#alive'],['oge', 'is', 'beautiful'],
                ['Ade', 'the', '#comedian', 'de', '#rich'],['Jesus', 'wept']]
res = [j if j.startswith("#") else "_"+j for i in ex for j in i]
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61