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!
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']
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')))
First I'd write a simple predicate function that determines whether or not a value should be included. Let's pretend that in this list of integers you only want to include those numbers >0
.
def is_strictly_positive(x):
return x > 0
Then you can have your whole list of numbers:
lst = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
And filter them:
filter(is_strictly_positive, lst) # 1 2 3 4 5 6 7
which creates a filter
object -- a generator that produces the values you need once. If you need a whole list, you can either do:
new_lst = list(filter(is_strictly_positive, lst)) # [1, 2, 3, 4, 5, 6, 7]
or, idiomatically, use a list comprehension
new_lst = [x for x in lst if is_strictly_positive(x)] # [1, 2, 3, 4, 5, 6, 7]
You can also use itertools.compress
to produce a similar result to filter
, but it's a little over-engineered in this simple case.
new_lst_gen = itertools.compress(lst, map(is_strictly_positive, lst)) # 1 2 3 4 5 6 7
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']
The itertools
module has many useful functions:
from itertools import compress, dropwhile, takewhile, filterfalse
condition1 = True
condition2 = False
condition3 = True
l = list(range(10))
print(list(compress(['a', 'b', 'c'], [condition1, condition2, condition3])))
# ['a', 'c']
print(list(dropwhile(lambda x: x > 5, l)))
# [5, 6, 7, 8, 9]
print(list(takewhile(lambda x: x < 5, l)))
# [0, 1, 2, 3, 4]
print(list(filterfalse(lambda x: x % 2, l))) # returns elements whose predicates == False
# [0, 2, 4, 6, 8]
Another one line approach, which is more Pythonic in my opinion, would be:
add_two = True
my_list = ['one'] + ['two'] * add_two + ['three']
In case of multiple conditionned elements, I think other alternatives, such as list of bools, should be used.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.