列表理解中的if/else

如何用空字符串替换所有None,然后调用某个函数f

[f(x) for x in xs if x is not None else '']
1616196 次浏览

你完全可以做到。这只是一个排序问题:

[f(x) if x is not None else '' for x in xs]

总的来说,

[f(x) if condition else g(x) for x in sequence]

并且,对于仅具有if条件的列表推导,

[f(x) for x in sequence if condition]

请注意,这实际上使用了不同的语言结构,条件表达式,它本身不是理解语法的一部分,而for…in之后的if是列表推导的一部分,用于过滤器源可迭代元素。


条件表达式可用于您希望根据某些条件在两个表达式值之间进行选择的各种情况。这与其他语言中存在的三元运算符#0相同。例如:

value = 123print(value, 'is', 'even' if value % 2 == 0 else 'odd')

一种方式:

def change(x):if x is None:return f(x)else:return ''
result = [change(x) for x in xs]

虽然你有:

result = map(change, xs)

或者您可以使用lambda内联。

下面是另一个说明性的例子:

>>> print(", ".join(["ha" if i else "Ha" for i in range(3)]) + "!")Ha, ha, ha!

它利用了这样一个事实,即if i0的计算结果为False,对函数range()生成的所有其他值的计算结果为True。因此,列表推导的计算结果如下:

>>> ["ha" if i else "Ha" for i in range(3)]['Ha', 'ha', 'ha']

具体问题已经在前面的答案中解决了,所以我将讨论在列表推导中使用条件的一般想法。

下面是一个示例,展示了如何在列表理解中编写条件:

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list
# Extract non-strings from X to new listX_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 isX_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

请注意,在X_non_str的第一个列表推导中,顺序是:

表达式进行项目迭代如果条件

X_str_changed的最后一个列表推导中,顺序是:

表情1如果条件否则表情2进行项目迭代

我总是觉得很难记住表情1必须在如果之前,表情2必须在否则之后。我的大脑希望两者都在之前或之后。

我想它是这样设计的,因为它类似于正常的语言,例如“我想呆在里面如果下雨,否则我想出去”

用简单的英语上面提到的两种类型的列表推导可以声明为:

只有if

extract_apple进行苹果apple_box如果apple_is_ripe

if/else

mark_apple如果apple_is_ripe否则leave_it_unmarked进行苹果apple_box

其他解决方案对于单个if/else构造非常好。然而,列表推导中的三元语句可能难以阅读。

使用函数有助于提高易读性,但是这样的解决方案很难在映射是输入的工作流中扩展或调整。字典可以减轻这些担忧:

xs = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]
d = {None: '', 'filler': 'manipulated'}
res = [d.get(x, x) for x in xs]
print(res)
['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']
# coding=utf-8
def my_function_get_list():my_list = [0, 1, 2, 3, 4, 5]
# You may use map() to convert each item in the list to a string,# and then join them to print my_list
print("Affichage de my_list [{0}]".format(', '.join(map(str, my_list))))
return my_list

my_result_list = [(number_in_my_list + 4,  # Condition is False : append number_in_my_list + 4 in my_result_listnumber_in_my_list * 2  # Condition is True : append number_in_my_list * 2 in my_result_list)
[number_in_my_list % 2 == 0]  # [Condition] If the number in my list is even
for number_in_my_list in my_function_get_list()  # For each number in my list]
print("Affichage de my_result_list [{0}]".format(', '.join(map(str, my_result_list))))

(venv)$pythonlist_comp.py
my_list[0,1,2,3,4,5]
my_result_list[0,5,4,7,8,9]

为了你:row = [('', unicode(x.strip()))[x is not None] for x in row]

不需要三元if/that/ther。在我看来,你的问题需要这样的答案:

row = [unicode((x or '').strip()) for x in row]

从可迭代对象中的项目创建列表

似乎最好先概括所有可能的形式,而不是给出问题的具体答案。否则,读者将不知道答案是如何确定的。以下是我在头痛之前想出的一些广义形式,试图决定是否可以在最后一种形式中使用最后一个其他从句。

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

item的值不需要在任何条件子句中使用。conditional3可以用作向输出列表添加或不添加值的开关。

例如,要创建一个从原始字符串列表中删除空字符串或空格字符串的新列表:

newlist = [s for s in firstlist if s.strip()]

它与如何执行列表理解有关。

请牢记以下几点:

[ expression for item in list if conditional ]

相当于:

for item in list:if conditional:expression

其中expression的格式略有不同(想想在句子中切换主语和动词的顺序)。

因此,您的代码[x+1 for x in l if x >= 45]这样做:

for x in l:if x >= 45:x+1

但是,这段代码[x+1 if x >= 45 else x+5 for x in l]这样做(在重新排列expression之后):

for x in l:if x>=45: x+1else: x+5

你可以在理解中组合条件逻辑:

 ps = PorterStemmer()stop_words_english = stopwords.words('english')best = sorted(word_scores.items(), key=lambda x: x[1], reverse=True)[:10000]bestwords = set([w for w, s in best])

def best_word_feats(words):return dict([(word, True) for word in words if word in bestwords])
# with stemmerdef best_word_feats_stem(words):return dict([(ps.stem(word), True) for word in words if word in bestwords])
# with stemmer and not stopwordsdef best_word_feats_stem_stop(words):return dict([(ps.stem(word), True) for word in words if word in bestwords and word not in stop_words_english])
[f(x) if x != None else '' for x in xs]

列表理解语法:

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

让我们用这个问题来回顾一些概念。我认为最好先看看基本面,这样你就可以推断出不同的情况。

其他答案提供了你问题的具体答案。我会先给出一些大致的背景,然后再回答这个问题。

基本面

列表推导中的if/else语句涉及两件事:

  • 列表理解
  • 条件表达式(三元运算符)

1.清单理解

它们提供是创建列表的简洁方法。

它的结构包括:“包含表达式后跟for子句的括号,然后是零个或多个for或if子句”。

案例1

这里我们没有条件。可迭代对象中的每个项目都被添加到new_list

new_list = [expression for item in iterable]new_list = [x for x in range(1, 10)]> [1, 2, 3, 4, 5, 6, 7, 8, 9]

案例2

这里我们有一个条件。

例1

条件:只有甚至的数字将被添加到new_list

new_list = [expression for item in iterable if condition == True]new_list = [x for x in range(1, 10) if x % 2 == 0]> [2, 4, 6, 8]

例2

条件:只有3的倍数甚至的数字将被添加到new_list

new_list = [expression for item in iterable if condition == True]new_list = [x for x in range(1, 10) if x % 2 == 0 if x % 3 == 0]> [6]

但是,如果我们在new_list中使用两个if,我们怎么会有一个条件呢?

前面的表达式可以写成:

new_list = [x for x in range(1, 10) if x % 2 and x % 3 == 0]> [6]

我们只使用一个if语句。

这就像做:

new_list = []for x in range(1, 10):if x % 2 == 0 and x % 3 == 0:new_list.append(x)> [6]

例3

为了便于讨论,您也可以使用or

条件:甚至数字或3的倍数将被添加到new_list

new_list = [x for x in range(1, 10) if x % 2 == 0 or x % 3 == 0]> [2, 3, 4, 6, 8, 9]

案件3

不止一个条件:

这里我们需要条件表达式(三元运算符)的帮助。

2.条件表达式

什么是条件表达式?顾名思义:一个有条件的Python表达式。

<Exp1> if condition else <Exp2>

首先计算condition。如果conditionTrue,则计算并返回<Exp1>。如果conditionFalse,则计算并返回<Exp2>

具有多个条件的条件表达式:

<Exp1> if condition else <Exp2> if condition else <Exp3>...

真正的Python的例子:

age = 12s = 'minor' if age < 21 else 'adult'> minor

s的值以age值为条件。

3.带条件的列表理解

我们像这样把列表理解和条件组合在一起。

new_list = [<Conditional Expression> for <item> in <iterable>]
new_list = [<Exp1> if condition else <Exp2> if condition else <Exp3> for <item> in <iterable>]

条件:甚至数字将被添加为'even',数字3将被添加为'number three',其余的将被添加为'odd'

new_list = ['even' if x % 2 == 0 else 'number three' if x == 3 else 'odd'for x in range(1, 10)]> ['odd', 'even', 'number three', 'even', 'odd', 'even', 'odd', 'even', 'odd']

问题的答案

[f(x) for x in xs if x is not None else '']

这里我们对列表的结构有一个问题:for x in xs应该在表达式的末尾。

正确做法:

[f(x) if x is not None else '' for x in xs]

进一步阅读:

Python有三元条件运算符吗?