if/else在Python的列表理解中?

AP2*_*257 791 python list-comprehension

如何在Python中执行以下操作?

row = [unicode(x.strip()) for x in row if x is not None else '']
Run Code Online (Sandbox Code Playgroud)

实质上:

  1. 用空字符串替换所有Nones,然后
  2. 执行功能.

pok*_*oke 1219

你完全可以做到这一点,这只是一个订购问题:

[unicode(x.strip()) if x is not None else '' for x in row]
Run Code Online (Sandbox Code Playgroud)

请注意,这实际上使用了不同的语言构造,一个条件表达式,它本身不是理解语法的一部分,而if后面if是列表推导的一部分,用于过滤源迭代中的元素.

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

[f(x) if condition else g(x) for x in sequence]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,if/else现在是"三元运算符"语法而不是列表推导语法. (126认同)
  • 所以诀窍就是"在列表压缩中我写的如果之前我还要添加其他部分".因为如果我的`l = [2,3,4,5]`那么`[x if x%2 == 0 for x in l]`给我错误,而`[x if x%2 == 0 else 200 for x in l]`有效.是的我知道过滤它我应该写`[x for x in l if x%2 == 0]`.抱歉打扰.感谢您的回答. (16认同)
  • 这就是为什么我更喜欢将三元运算符放在括号中,它更清楚地表明它只是一个正常的表达式而不是理解. (8认同)
  • [python docs提到三元运算符](http://docs.python.org/3/faq/programming.html#is-there-an-equivalent-of-cs-ternary-operator).请注意,它需要else,否则它不起作用. (5认同)
  • @Drewdin List comprehensions不支持在迭代期间中断.那么你将不得不使用正常的循环. (3认同)
  • @Phani是的,它仍然是一个列表理解,只是在表达式中有条件. (2认同)
  • 两种语法之间存在区别:`[final-expr for x in start-expr if cond-expr]` 是“包含 `start-expr` 中每个元素的 `final-expr` 的结果,如只要 `cond-expr` 在此元素的上下文中为 true。碰巧这两个表达式也可以使用三元运算符。请记住,推导式中的“if”具有 * 的能力过滤*结果,即最终得到的元素少于“start-expr”中的元素。“expr1 if cond else expr2”三元表达式的情况并非如此。 (2认同)
  • 例如:`[x for x in range(50)if(x%3)== 0]`将返回一个可被3整除的整数列表.` [x if(x%3)== 0 for x in range (50)]`无效,因为`x if(x%3)== 0`不是有效的表达式.@Grijesh,这里是你的规则的反例(如果之前/之后):`[x for x in range(50)if((x%3)== 0 if x> 20 else False)]`.此理解的过滤条件仅匹配可被3整除且大于20的整数. (2认同)

Guz*_*ero 121

我们通过这个问题来回顾一下一些概念。我认为最好先了解基本原理,这样您就可以推断出不同的情况。

其他答案提供了您问题的具体答案。我将首先给出一些一般背景,然后我将回答这个问题。

基础知识

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]
Run Code Online (Sandbox Code Playgroud)

案例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]
Run Code Online (Sandbox Code Playgroud)

实施例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]
Run Code Online (Sandbox Code Playgroud)

if但是如果我们在 中使用两个条件,为什么我们只有一个条件呢new_list

先前的表达式可以写为:

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

我们只使用一个if语句。

这就像做:

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

实施例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]
Run Code Online (Sandbox Code Playgroud)

案例3

多个条件:

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

2.条件表达式

什么是条件表达式?顾名思义:具有某些条件的 Python 表达式。

<Exp1> if condition else <Exp2>
Run Code Online (Sandbox Code Playgroud)

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

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

<Exp1> if condition else <Exp2> if condition else <Exp3>...    
Run Code Online (Sandbox Code Playgroud)

来自Real Python的示例:

age = 12
s = 'minor' if age < 21 else 'adult'
> minor
Run Code Online (Sandbox Code Playgroud)

的值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>]
Run Code Online (Sandbox Code Playgroud)

条件:偶数加为'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']
Run Code Online (Sandbox Code Playgroud)

问题的答案

[f(x) for x in xs if x is not None else '']
Run Code Online (Sandbox Code Playgroud)

这里我们遇到了列表结构的问题:for x in xs应该位于表达式的末尾。

正确方法:

[f(x) if x is not None else '' for x in xs]
Run Code Online (Sandbox Code Playgroud)

进一步阅读:

Python 有三元条件运算符吗?

  • 到目前为止,这是我在这里和其他地方可以找到的最佳答案。真的谢谢古兹曼·奥杰罗先生 (3认同)

Ada*_*erg 41

单程:

def change(f):
    if f is None:
        return unicode(f.strip())
    else:
        return ''

row = [change(x) for x in row]
Run Code Online (Sandbox Code Playgroud)

虽然你有:

row = map(change, row)
Run Code Online (Sandbox Code Playgroud)

或者你可以使用lambda内联.

  • 当你必须处理来自`if`表达式或其中的`else`s语句块中的代码的可能异常时,这也是一种很好的(也许是唯一的)技术.对于简单的案例,接受的答案更好. (13认同)

Ben*_*ngt 37

这是另一个说明性的例子:

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

它利用了这样的事实if i评估,以False0,并True通过函数生成的所有其他值range().因此,列表理解评估如下:

>>> ["ha" if i else "Ha" for i in range(3)]
['Ha', 'ha', 'ha']
Run Code Online (Sandbox Code Playgroud)


Tim*_*sen 31

在以前的答案中已经解决了具体问题,因此我将讨论在列表推导中使用条件的一般概念.

这是一个示例,显示如何在列表推导中编写条件:

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
Run Code Online (Sandbox Code Playgroud)

请注意,在第一个列表理解中X_non_str,顺序是:

expression1的, 如果是expression2

在最后的列表理解中X_str_changed,顺序是:

值1 ,如果 表达式 其他 值2 表达式2

我总是发现很难记住value1必须在if之前,value2必须在else之后.我的头想要在之前或之后.

我想它的设计就是这样,因为它类似于普通语言,例如" 如果下雨,我想留在里面,否则我想去外面"

  • 你可以两者兼得。例如,这个 Buzzless Fizzbuzz:`vals = list(range(40)); [val if val % 3 else "Fizz" for val in vals if val % 5]` 组合了结果列表中内容的表达式以及过滤条件。 (2认同)

小智 22

[f(x) if x != None else '' for x in xs]
Run Code Online (Sandbox Code Playgroud)

列表理解的语法:

[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]
Run Code Online (Sandbox Code Playgroud)


jpp*_*jpp 5

其他解决方案非常适合单个if/ else结构。但是,列表理解内的三元语句很难理解。

使用功能有助于提高可读性,但是在将映射作为输入的工作流中,很难扩展或适应这种解决方案。字典可以缓解这些问题:

row = [None, 'This', 'is', 'a', 'filler', 'test', 'string', None]

d = {None: '', 'filler': 'manipulated'}

res = [d.get(x, x) for x in row]

print(res)

['', 'This', 'is', 'a', 'manipulated', 'test', 'string', '']
Run Code Online (Sandbox Code Playgroud)


arb*_*oc7 5

它与列表理解的执行方式有关。

请记住以下几点:

[ expression for item in list if conditional ]
Run Code Online (Sandbox Code Playgroud)

相当于:

for item in list:
    if conditional:
        expression
Run Code Online (Sandbox Code Playgroud)

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

因此,您的代码[x+1 for x in l if x >= 45]执行以下操作:

for x in l:
    if x >= 45:
        x+1
Run Code Online (Sandbox Code Playgroud)

但是,此代码[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
Run Code Online (Sandbox Code Playgroud)