[英]if/else in a list comprehension
如何用空字符串替换所有None
,然后调用一些函数f
?
[f(x) for x in xs if x is not None else '']
你完全可以做到这一点。 这只是一个订购问题:
[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
是列表理解的一部分,用于从源迭代中过滤元素。
条件表达式可用于您希望根据某些条件在两个表达式值之间进行选择的各种情况。 这与存在于其他语言中的三元运算符?:
相同。 例如:
value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')
具体问题已经在之前的答案中解决了,所以我将讨论在列表推导中使用条件的一般想法。
这是一个示例,显示了如何在列表推导中编写条件:
X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a'] # Original list
# Extract non-strings from X to new list
X_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 is
X_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
的第一个列表推导中,顺序为:
可迭代if条件中的项目表达式
在X_str_changed
的最后一个列表理解中,顺序是:
表达式1 if条件else表达式2用于迭代中的项目
我总是很难记住expression1必须在if之前,而expression2必须在else之后。 我的头脑希望两者都在之前或之后。
我猜它是这样设计的,因为它类似于普通语言,例如“如果下雨我想呆在里面,否则我想出去”
用简单的英语来说,上面提到的两种类型的列表理解可以表述为:
仅if
:
如果apple_is_ripe ,则为apple_box中的苹果提取苹果
和if/else
mark_apple if apple_is_ripe else leave_it_unmarked for apple in apple_box
让我们用这个问题来回顾一些概念。 我认为首先了解基本面是很好的,这样您就可以推断出不同的情况。
其他答案为您的问题提供了具体答案。 我将首先给出一些一般背景,然后我会回答这个问题。
列表推导中的if/else
语句涉及两件事:
它们提供了一种简洁的方式来创建列表。
它的结构包括:“包含一个表达式的括号,后跟一个 for 子句,然后是零个或多个 for 或 if 子句”。
我们这里没有条件。 可迭代的每个项目都添加到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]
这里我们有一个条件。
示例 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]
不止一种情况:
这里我们需要条件表达式(三元运算符)的帮助。
什么是条件表达式? 顾名思义:一个有条件的 Python 表达式。
<Exp1> if condition else <Exp2>
首先评估condition
。 如果condition
为True
,则<Exp1>
被评估并返回。 如果condition
为False
,则评估并返回<Exp2>
。
具有多个条件的条件表达式:
<Exp1> if condition else <Exp2> if condition else <Exp3>...
来自Real Python的示例:
age = 12
s = 'minor' if age < 21 else 'adult'
> minor
s
的值取决于age
值。
我们像这样将列表推导式和条件式放在一起。
new_list = [<Conditional Expression> for <item> in <iterable>]
new_list = [<Exp1> if condition else <Exp2> if condition else <Exp3> for <item> in <iterable>]
条件:偶数加为'even'
,第三个加为'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]
进一步阅读:
单程:
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 i
对0
计算为False
,对函数range()
生成的所有其他值计算为True
。 因此,列表推导式评估如下:
>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']
其他解决方案非常适合单个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', '']
它与列表理解的执行方式有关。
请记住以下几点:
[ 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+1
else: x+5
[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]
从可迭代的项目中创建列表
似乎最好先概括所有可能的形式,而不是给出问题的具体答案。 否则,读者将不知道答案是如何确定的。 这是我在头疼之前想出的一些通用形式,试图决定是否可以在最后一种形式中使用最后的 else 子句。
[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
3 可用作向输出列表添加或不添加值的开关。
例如,要创建一个从原始字符串列表中删除空字符串或空白字符串的新列表:
newlist = [s for s in firstlist if s.strip()]
不需要三元 if/then/else。 在我看来,您的问题需要这个答案:
row = [unicode((x or '').strip()) for x in row]
您可以在理解中结合条件逻辑:
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 stemmer
def best_word_feats_stem(words):
return dict([(ps.stem(word), True) for word in words if word in bestwords])
# with stemmer and not stopwords
def 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])
# 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_list
number_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) $ python list_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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.