列表推导中的 if/else

2024-11-21 08:33:00
admin
原创
7
摘要:问题描述:如何将以下for包含if/ 的-loop 转换else为列表推导?results = [] for x in xs: results.append(f(x) if x is not None else '') ''如果x是 则应该输出None否则输出f(x)。我试过了:[f(x) for x...

问题描述:

如何将以下for包含if/ 的-loop 转换else为列表推导?

results = []
for x in xs:
    results.append(f(x) if x is not None else '')

''如果x是 则应该输出None否则输出f(x)。我试过了:

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

但它给出了一个SyntaxError。正确的语法是什么?


有关 的信息,请参阅Python 是否有三元条件运算符?... if ... else ...。有关 的信息

,请参阅带条件的列表推导式以根据条件省略值:[... for x in xs if x cond]有关的信息,

请参阅列表推导式条件中的 elif`elif`。


解决方案 1:

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

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

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


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

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

解决方案 2:

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

其他答案提供了对你的问题的具体答案。我将首先提供一些一般背景,然后再回答问题。

基本面

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]

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

先前的表达式可以写成:

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>...    

来自Real Python的一个例子:

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

的价值s是由age价值决定的。

  1. 带条件的列表推导


我们把列表推导和条件像这样放在一起。

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]

进一步阅读:

Python 有三元条件运算符吗?

解决方案 3:

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

以下示例显示了如何在列表推导式中编写条件语句:

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 for item in itable

我总是很难记住表达式1必须位于if之前,而表达式2必须位于else之后。我的大脑希望两者都位于之前或之后。

我猜它之所以这样设计是因为它类似于正常语言,例如“如果下雨我想呆在室内,否则我想出去”

用简单的英语来说,上面提到的两种列表推导式可以表述如下:

仅包含if

如果apple_is_ripe,则 apple_box中的苹果进行 extract_apple

以及if/else

如果 apple_is_ripe则 mark_apple否则如果 apple_box中的苹果*leave_it_unmarked*

解决方案 4:

单程:

def change(x):
    if x is None:
        return f(x)
    else:
        return ''

result = [change(x) for x in xs]

尽管你有:

result = map(change, xs)

或者您可以使用内联 lambda。

解决方案 5:

下面是另一个示例:

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

它利用了这样一个事实:对于if i, 求值为;对于 ,对于函数 生成的所有其他值 ,求值为 。因此,列表推导式求值如下:False`0Truerange()`

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

解决方案 6:

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

解决方案 7:

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

解决方案 8:

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

请记住以下几点:

[ 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

解决方案 9:

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

最好先概括所有可能的形式,而不是给出问题的具体答案。否则,读者将不知道答案是如何确定的。以下是我在为决定最后一个形式中是否可以使用最后一个 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不需要在任何条件子句中使用。Aconditional3可以用作开关,用于选择向输出列表添加或不添加值。

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

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

解决方案 10:

其他答案解释得很好,但我只是想补充一些关于在列表理解中使用哪个条件表达式的信息。

正如文档所述,列表推导式用于通过 for 循环创建列表,其一般结构如下:

[expression for item in iterable (0 or more if/for clauses)]

它可以创建:

  1. expression通过迭代计算列表,或者

  2. iterable如果if语句遵循初始for语句,则产生子序列

从上面的一般结构中,我们可以看出,else语句不能跟在for语句后面;for但可以跟在if虽然后面;因此以下是有效的代码:

[y for x in range(5) if x % 2 == 0 for y in range(x)]

因此,任何 if-else 控制流都必须在上面的评估中完成expression。此外,由于列表推导会创建一个列表,因此expression必须是可以分配给变量的表达式。因此,诸如 bare 之类的条件表达式if无法工作,因为我们不知道如果条件不为 True,值应该是什么。它类似于如何将变量定义xx = 10 if TrueSyntaxError。因此,如果expression包含条件语句,它必须包含else,类似于x = 10 if True else 5可以定义变量x

总而言之,使用 if/else 应被视为上述情况 (1) 的特殊情况,其中expression在迭代中进行评估,但要注意expression包含一个条件,如下所示:

[(expression1 if condition else expression2) for item in iterable]

  • 列表推导式中一个if语句跟在另一个for语句后面(上面的情况 (2))类似于用数学符号从给定集合中定义一个子集,因此[x for x in iterable if m<x<n]类似于{x ∈ iterable | m<x<n}

  • 由于列表推导会创建一个列表,如果创建列表不是目的,就不应该使用它;它不应该简单地用来编写一行 for 循环;所以不要写[print(x) for x in range(5)]例如。

解决方案 11:

没有必要使用三元 if/then/else。我认为您的问题需要这样的答案:

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

解决方案 12:

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

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

解决方案 13:

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

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用