如何用条件元素组成列表

时间:2019-01-21 22:24:06

标签: python

我用python编程了一段时间,我发现这种语言对程序员非常友好,所以也许有一种我不知道如何用条件元素组成列表的技术。简化的示例是:

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

基本上,我正在寻找一种方便的方法来创建一个包含在某些特定条件下添加的列表的列表。

一些看起来不太好的选择:

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"]

有什么可以简化它的吗?干杯!

6 个答案:

答案 0 :(得分:4)

如果您可以创建代表希望从候选列表中保留哪些元素的布尔列表,则可以非常简洁地执行此操作。例如:

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']

如果您可以使用numpy,它将变得更加简洁:

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']

最后,根据注释中的建议,您可以使用itertools.compress()。请注意,这将返回一个迭代器,因此您必须解压缩它。

from itertools import compress
print([v for v in compress(candidates, include)])
# ['one', 'two', 'four']

答案 1 :(得分:2)

您可以在一行中写:

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

或使用列表理解:

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

或删除Falsy值的功能方法:

my_list = list(filter(None, ('one', 'two' if add_two else '', 'three')))

答案 2 :(得分:2)

首先,我将编写一个简单的谓词函数,以确定是否应包含一个值。我们假设在此整数列表中,您只想包含那些数字>0

def is_strictly_positive(x):
    return x > 0

然后,您可以获取整个数字列表:

lst = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7]

并对其进行过滤:

filter(is_strictly_positive, lst)  # 1 2 3 4 5 6 7

创建一个filter对象-一个生成器,生成一次您需要的值。如果您需要整个列表,则可以执行以下操作:

new_lst = list(filter(is_strictly_positive, lst))  # [1, 2, 3, 4, 5, 6, 7]

或者习惯上使用列表理解

new_lst = [x for x in lst if is_strictly_positive(x)]  # [1, 2, 3, 4, 5, 6, 7]

您还可以使用itertools.compress来产生与filter类似的结果,但是在这种简单情况下,它的设计有些过分。

new_lst_gen = itertools.compress(lst, map(is_strictly_positive, lst))  # 1 2 3 4 5 6 7

答案 3 :(得分:1)

此方法使用None标记值来删除要删除的值,然后最后将其过滤掉。如果您的数据已经包含None,则可以create another sentinel object代替。

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']

答案 4 :(得分:0)

itertools模块具有许多有用的功能:

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]

答案 5 :(得分:0)

另一种在我看来更 Pythonic 的方法是:

{{1}}

如果有多个条件元素,我认为应该使用其他替代方法,例如 bool 列表。