Blog Post #122: if-else in a List Comprehension: The Ternary Operator

In Post #121, we learned how to add an if clause to the end of a list comprehension to filter items. This is great for deciding whether to include an item in the new list. But what if we want to include every item from the original list, but transform each one differently based on a condition?

For example, what if we want to create a new list that labels each number from an original list as either “Even” or “Odd”? A simple if filter can’t do this. For this, we need an if-else structure, which we can achieve using the ternary operator we first met in Post #30.

Transformation vs. Filtering

Let’s be clear on the two different goals, as this determines where the if logic goes in a comprehension:

  • Filtering (using if at the end): We want to select a subset of the original items. The if clause acts as a gate.
    • [num for num in numbers if num > 0]
  • Conditional Transformation (using if-else at the beginning): We want a new list of the same length as the original, but where each item has been changed based on a condition.

The Ternary Operator in a Comprehension

To achieve an if-else transformation, we use the ternary operator value_if_true if condition else value_if_false as the main expression part of the comprehension.

The syntax looks like this:

new_list = [expression_if_true if condition else expression_if_false for item in iterable]

Notice the placement: the entire if-else logic comes before the for loop.

Let’s solve our “Even”/”Odd” labeling problem. First, the standard for loop way:

numbers = [1, 2, 3, 4, 5]
labels = []

for number in numbers:
    if number % 2 == 0:
        labels.append("Even")
    else:
        labels.append("Odd")

print(labels)

Now, let’s do the same thing in one line with a list comprehension:

numbers = [1, 2, 3, 4, 5]

labels = ["Even" if number % 2 == 0 else "Odd" for number in numbers]

print(labels)

Both produce the same output: ['Odd', 'Even', 'Odd', 'Even', 'Odd'].

The comprehension ["Even" if number % 2 == 0 else "Odd" for number in numbers] can be read as: “For each number in numbers, produce the value ‘Even’ if the number is even, otherwise produce the value ‘Odd’, and collect all these results into a new list.”

Putting it All Together: Transformation and Filtering

You can even combine both techniques in a single, powerful comprehension! The if-else transformation still goes at the beginning, and the if filter still goes at the end.

The full syntax is:

[transform_expression if-else for item in iterable if filter_condition]

Let’s create a list of “Even”/’Odd’ labels, but only for numbers greater than 5.

numbers = [1, 2, 3, 4, 5, 6, 7, 8]

# The 'if num > 5' is the filter
# The '"Even" if ... else "Odd"' is the transformation
labels = ["Even" if num % 2 == 0 else "Odd" for num in numbers if num > 5]

print(labels)

The output will be: ['Even', 'Odd', 'Even'].

Python first applies the filter (if num > 5), which selects the items [6, 7, 8]. Then, it applies the if-else transformation expression to each of those filtered items.

What’s Next?

You now know how to use both filtering (if at the end) and conditional transformation (if-else at the beginning) in your list comprehensions. This allows you to write incredibly expressive and concise one-liners for creating new lists.

The power of comprehensions isn’t limited to just lists. Python provides a similar, elegant syntax for creating sets and dictionaries. In Post #123, we will expand our knowledge and learn about set and dictionary comprehensions.

Author

Debjeet Bhowmik

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com

Leave a Comment