256

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?

1
  • 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. Commented Jul 18, 2018 at 6:45

6 Answers 6

477

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.

Sign up to request clarification or add additional context in comments.

4 Comments

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?
@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)
@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.
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: ?
32
[x if x % 2 else x * 100 for x in range(1, 10) ]

Comments

20

You can do that with list comprehension too:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A

2 Comments

Very nice. A boolean slice. Thanks you just gave me an easier to read solution.
You can also double assign like so: A,B = [10,11][a==19],[1,14][a==20]
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]
>>>

Comments

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) 

Comments

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]

1 Comment

I don't see what information this answer adds over the much older and explained existing answers...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.