if/else in a list comprehension

Posted on

Solving problem is about exposing yourself to as many situations as possible like if/else in a list comprehension and practice these strategies over and over. With time, it becomes second nature and a natural way you approach any problems in general. Big or small, always start with a plan, use other strategies mentioned here till you are confident and ready to code the solution.
In this post, my aim is to share an overview the topic about if/else in a list comprehension, which can be followed any time. Take easy to follow this discuss.

if/else in a list comprehension

How can I do the following in Python?

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

Essentially:

  1. replace all the Nones with empty strings, and then
  2. carry out a function.
Asked By: AP257

||

Answer #1:

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')
Answered By: poke

Answer #2:

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

Answered By: Tim Skov Jacobsen

Answer #3:

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.

Answered By: Adam Vandenberg

Answer #4:

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']
Answered By: Bengt

Answer #5:

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', '']
Answered By: jpp

Answer #6:

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
Answered By: arboc7

Answer #7:

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()]
Answered By: Hewey Dewey

Answer #8:

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]
Answered By: MD. ABU SAYED

Leave a Reply

Your email address will not be published.