[python] if else in a list comprehension

I have a list l:

l = [22, 13, 45, 50, 98, 69, 43, 44, 1]

For numbers above 45 inclusive, I would like to add 1; and for numbers less than it, 5.

I tried

[x+1 for x in l if x >= 45 else x+5]

But it gives me a syntax error. How can I achieve an ifelse like this in a list comprehension?

This question is related to python list list-comprehension if-statement

The answer is


The specific problem has already been solved in previous answers, so I will address the general idea of using conditionals inside list comprehensions.

Here is an example that shows how conditionals can be written inside a list comprehension:

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list

# Extract non-strings from X to new list
X_non_str = [el for el in X if not isinstance(el, str)]  # When using only 'if', put 'for' in the beginning

# Change all strings in X to 'b', preserve everything else as is
X_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

Note that in the first list comprehension for X_non_str, the order is:

expression for item in iterable if condition

and in the last list comprehension for X_str_changed, the order is:

expression1 if condition else expression2 for item in iterable

I always find it hard to remember that expression1 has to be before if and expression2 has to be after else. My head wants both to be either before or after.

I guess it is designed like that because it resembles normal language, e.g. "I want to stay inside if it rains, else I want to go outside"

In plain English the two types of list comprehensions mentioned above could be stated as:

With only if:

extract_apple for apple in apple_box if apple_is_ripe

and with if/else

mark_apple if apple_is_ripe else leave_it_unmarked for apple in apple_box


The other solutions are great for a single if / else construct. However, ternary statements within list comprehensions are arguably difficult to read.

Using a function aids readability, but such a solution is difficult to extend or adapt in a workflow where the mapping is an input. A dictionary can alleviate these concerns:

row = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]

d = {None: '', 'filler': 'manipulated'}

res = [d.get(x, x) for x in row]

print(res)

['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']

I just had a similar problem, and found this question and the answers really useful. Here's the part I was confused about. I'm writing it explicitly because no one actually stated it simply in English:

The iteration goes at the end.

Normally, a loop goes

for this many times:
    if conditional: 
        do this thing
    else:
        do something else  

Everyone states the list comprehension part simply as the first answer did,

[ expression for item in list if conditional ] 

but that's actually not what you do in this case. (I was trying to do it that way)

In this case, it's more like this:

[ expression if conditional else other thing for this many times ] 

Here is another illustrative example:

>>> print(", ".join(["ha" if i else "Ha" for i in range(3)]) + "!")
Ha, ha, ha!

It exploits the fact that if i evaluates to False for 0 and to True for all other values generated by the function range(). Therefore the list comprehension evaluates as follows:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']

You can combine conditional logic in a comprehension:

 ps = PorterStemmer()
 stop_words_english = stopwords.words('english')
 best = sorted(word_scores.items(), key=lambda x: x[1], reverse=True)[:10000]
 bestwords = set([w for w, s in best])


 def best_word_feats(words):
   return dict([(word, True) for word in words if word in bestwords])

 # with stemmer
 def best_word_feats_stem(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords])

 # with stemmer and not stopwords
 def best_word_feats_stem_stop(words):
   return dict([(ps.stem(word), True) for word in words if word in bestwords and word not in stop_words_english])

[x+1 if x >= 45 else x+5 for x in l]

And for a reward, here is the comment, I wrote to remember this the first time I did this error:

Python's conditional expression is a if C else b and can't be used as:

[a for i in items if C else b]

The right form is:

[a if C else b for i in items]

Even though there is a valid form:

[a for i in items if C]

But that isn't the same as that is how you filter by C, but they can be combined:

[a if tC else b for i in items if fC]

you can do this

row = [unicode(x.strip()) if x != None else '' for x in row]

Some Syntax for List comprehension :

[item if condition else item for item in items]
[f(item) if condition else value for item in items]
[item if condition for item in items]
[value if condition else value1 if condition1 else value2]

There isn't any need for ternary if/then/else. In my opinion your question calls for this answer:

row = [unicode((x or '').strip()) for x in row]

You can also put the conditional expression in brackets inside the list comprehension:

    l = [22, 13, 45, 50, 98, 69, 43, 44, 1]
    print [[x+5,x+1][x >= 45] for x in l]

[false,true][condition] is the syntax


One way:

def change(f):
    if f is None:
        return unicode(f.strip())
    else:
        return ''

row = [change(x) for x in row]

Although then you have:

row = map(change, row)

Or you can use a lambda inline.


The reason you're getting this error has to do with how the list comprehension is performed.

Keep in mind the following:

[ expression for item in list if conditional ]

Is equivalent to:

for item in list:
    if conditional:
        expression

Where the expression is in a slightly different format (think switching the subject and verb order in a sentence).

Therefore, your code [x+1 for x in l if x >= 45] does this:

for x in l:
    if x >= 45:
        x+1

However, this code [x+1 if x >= 45 else x+5 for x in l] does this (after rearranging the expression):

for x in l:
    if x>=45: x+1
    else: x+5

# coding=utf-8

def my_function_get_list():
    my_list = [0, 1, 2, 3, 4, 5]

    # You may use map() to convert each item in the list to a string, 
    # and then join them to print my_list

    print("Affichage de my_list [{0}]".format(', '.join(map(str, my_list))))

    return my_list


my_result_list = [
   (
       number_in_my_list + 4,  # Condition is False : append number_in_my_list + 4 in my_result_list
       number_in_my_list * 2  # Condition is True : append number_in_my_list * 2 in my_result_list
   )

   [number_in_my_list % 2 == 0]  # [Condition] If the number in my list is even

   for number_in_my_list in my_function_get_list()  # For each number in my list
]

print("Affichage de my_result_list [{0}]".format(', '.join(map(str, my_result_list))))

(venv) $ python list_comp.py
Affichage de my_list [0, 1, 2, 3, 4, 5]
Affichage de my_result_list [0, 5, 4, 7, 8, 9]

So, for you: row = [('', unicode(x.strip()))[x is not None] for x in row]


You can totally do that. It's just an ordering issue:

[unicode(x.strip()) if x is not None else '' for x in row]

In general,

[f(x) if condition else g(x) for x in sequence]

And, for list comprehensions with if conditions only,

[f(x) for x in sequence if condition]

Note that this actually uses a different language construct, a conditional expression, which itself is not part of the comprehension syntax, while the if after the for…in is part of list comprehensions and used to filter elements from the source iterable.


Conditional expressions can be used in all kinds of situations where you want to choose between two expression values based on some condition. This does the same as the ternary operator ?: that exists in other languages. For example:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')

You must put the expression at the beginning of the list comprehension, an if statement at the end filters elements!

[x+1 if x >= 45 else x+5 for x in l]

Like in [a if condition1 else b for i in list1 if condition2], the two ifs with condition1 and condition2 doing two different things. The part (a if condition1 else b) is from a lambda expression:

lambda x: a if condition1 else b

while the other condition2 is another lambda:

lambda x: condition2

Whole list comprehension can be regard as combination of map and filter:

map(lambda x: a if condition1 else b, filter(lambda x: condition2, list1))

Make a list from items in an iterable

It seems best to first generalize all the possible forms rather than giving specific answers to questions. Otherwise, the reader won't know how the answer was determined. Here are a few generalized forms I thought up before I got a headache trying to decide if a final else' clause could be used in the last form.

[expression1(item)                                        for item in iterable]

[expression1(item) if conditional1                        for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable]

[expression1(item) if conditional1 else expression2(item) for item in iterable if conditional2]

The value of item doesn't need to be used in any of the conditional clauses. A conditional3 can be used as a switch to either add or not add a value to the output list.

For example, to create a new list that eliminates empty strings or whitespace strings from the original list of strings:

newlist = [s for s in firstlist if s.strip()]

It has to do with how the list comprehension is performed.

Keep in mind the following:

[ expression for item in list if conditional ]

Is equivalent to:

for item in list:
    if conditional:
        expression

Where the expression is in a slightly different format (think switching the subject and verb order in a sentence).

Therefore, your code [x+1 for x in l if x >= 45] does this:

for x in l:
    if x >= 45:
        x+1

However, this code [x+1 if x >= 45 else x+5 for x in l] does this (after rearranging the expression):

for x in l:
    if x>=45: x+1
    else: x+5

You could move the conditional to:

v = [22, 13, 45, 50, 98, 69, 43, 44, 1]
[ (x+1 if x >=45 else x+5)  for x in v ]

But it's starting to look a little ugly, so you might be better off using a normal loop. Note that I used v instead of l for the list variable to reduce confusion with the number 1 (I think l and O should be avoided as variable names under any circumstances, even in quick-and-dirty example code).


Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to list

Convert List to Pandas Dataframe Column Python find elements in one list that are not in the other Sorting a list with stream.sorted() in Java Python Loop: List Index Out of Range How to combine two lists in R How do I multiply each element in a list by a number? Save a list to a .txt file The most efficient way to remove first N elements in a list? TypeError: list indices must be integers or slices, not str Parse JSON String into List<string>

Examples related to list-comprehension

Python for and if on one line Inline for loop Are list-comprehensions and functional functions faster than "for loops"? How to frame two for loops in list comprehension python List comprehension on a nested list? One-line list comprehension: if-else variants Transpose a matrix in Python Why is there no tuple comprehension in Python? remove None value from a list without removing the 0 value Pythonic way to print list items

Examples related to if-statement

How to use *ngIf else? SQL Server IF EXISTS THEN 1 ELSE 2 What is a good practice to check if an environmental variable exists or not? Using OR operator in a jquery if statement R multiple conditions in if statement Syntax for an If statement using a boolean How to have multiple conditions for one if statement in python Ifelse statement in R with multiple conditions If strings starts with in PowerShell Multiple conditions in an IF statement in Excel VBA