This question already has an answer here:
-
if else in a list comprehension [duplicate]
8 answers
I have the following list comprehension.
return [tower for tower in state if tower != space else []]
But when I run it, python spits back this error:
return [tower for tower in state if tower != space else []]
^
SyntaxError: invalid syntax
If I remove the else statement, it runs fine. Am I writing the else statement wrong somehow?
List comprehensions support if
but not else
because the if
section filters elements, you either include an element or you don't include it, a boolean choice.
If you wanted to use a conditional expression to build the iterable part of the for
loop, use parentheses:
return [tower for tower in (state if tower != space else [])]
but I suspect that you wanted to alter the value of the expression in the element expression instead; that's not filtering, you are simply producing a different value for certain items. Use a conditional expression to produce your values:
return [tower if tower != space else [] for tower in state]
or if you really wanted to filter, simply omit the else
:
return [tower for tower in state if tower != space]
When constructing a list comprehension, remember that you need to read the expression as nested from left to right, with the final expression producing the result out on the left:
[element_producing_expression for name in iterable if filter_expression]
is the moral equivalent of:
for name in iterable:
if filter_expression:
element_producing_expression
where you can use as many nested loops and if
filters as your use case requires.
The three options I described above are then the same as:
# conditional expression producing the iterable
for tower in (state if tower != space else []):
tower
# conditional expression in the element expression
for tower in state:
tower if tower != space else []
# filtering expression with no else
for tower in state:
if tower != space:
tower
You are putting the else in the for
clause of the comprehension, but you need to put the entire if/else expression in the target expression:
[tower if tower != space else [] for tower in state]
When you use for tower in state if <condition>
you are saying you want to not even make use of items in state
if they don't satisfy the condition. In this case, you can't use an else
, because all you can do is either process each item (including something in the list comprehension result), or not.
The X if Y else Z
, on the other hand, is a normal expression that can be used as the target expression of the list comprehension. This means that every element in the source iterable will generate an element in the result, but the if/else determines what that result item will be.
How about this:
[tower if tower != space else [] for tower in state]
That's because python doesn't support if-else
in list comprehension filters, only if
clauses.
You can however achieve the result you want by using a conditional expression
[tower if tower != space else [] for tower in state]