Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compose a list with conditional elements

Tags:

python

I program in python for a while and I've found that this language is very programmer friendly, so that maybe there is a technique that I don't know how to compose a list with conditional elements. The simplified example is:

# in pseudo code
add_two = True
my_list = [
  "one",
  "two" if add_two,
  "three",
]

Basically I'm looking for a handy way to create a list that contains some that are added under some specific condition.

Some alternatives that don't look such nice:

add_two = True

# option 1
my_list = []
my_list += ["one"]
my_list += ["two"] if add_two else []
my_list += ["three"]


# option 2
my_list = []
my_list += ["one"]
if add_two: my_list += ["two"]
my_list += ["three"]

Is there something that can simplify it? Cheers!

like image 853
Piotr Paczkowski Avatar asked Jan 21 '19 22:01

Piotr Paczkowski


3 Answers

If you can create a list of bools representing what elements you want to keep from a candidate list, you can do this pretty succinctly. For example:

candidates = ['one', 'two', 'three', 'four', 'five']
include = [True, True, False, True, False]
result = [c for c, i in zip(candidates, include) if i]
print(result)
# ['one', 'two', 'four']

If you can use numpy, this gets even more succinct:

import numpy as np
candidates = np.array(['one', 'two', 'three', 'four', 'five'])
include = [True, True, False, True, False]
print(candidates[include])  # can use boolean indexing directly!
# ['one', 'two', 'four']

Finally, as suggested in a comment, you can use itertools.compress(). Note that this returns an iterator, so you have to unpack it.

from itertools import compress
print([v for v in compress(candidates, include)])
# ['one', 'two', 'four']
like image 138
Engineero Avatar answered Nov 10 '22 06:11

Engineero


In one line you can write:

my_list = ['one'] + (['two'] if add_two else []) + ['three']

Or use a list comprehension:

my_list = [x for x in ('one', 'two' if add_two else '', 'three') if x]

Or the functional way to remove Falsy values:

my_list = list(filter(None, ('one', 'two' if add_two else '', 'three')))
like image 24
jpp Avatar answered Nov 10 '22 05:11

jpp


This approach uses a None sentinel value for values to remove, then filters them out at the end. If your data contains None already, you can create another sentinel object to use instead.

add_two = True
my_list = [
    "one",
    "two" if add_two else None,
    "three",
]

my_list = [e for e in my_list if e is not None]

print(my_list)
# ['one', 'two', 'three']
like image 30
Ben Avatar answered Nov 10 '22 06:11

Ben