“如果……或者……”的陈述在列表理解中?

2024-03-29 08:24:52 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python3.4.2中,有没有一种方法可以使用“if。。。或者在列表理解中的“陈述”?

示例:

filtered_list = [x for x in other_list
                 if not '    ' in x or '    ' in other_list[int(other_list.index(x) -1)]]
                                                 #^item just before "x" in "other_list"

我知道这个命令不起作用。我知道这个也不是:

filtered_list = [x for x in other_list
                 if not ('    ' in x) or ('    ' in other_list[int(other_list.index(x) -1)])]
                                                    #^item just before "x" in "other_list"

有办法吗?一个“for”循环会更容易阅读,但我正在努力推动我对列表理解的理解。提前谢谢。

(奇怪的是,我在stackoverflow上找不到这样的问题。)


Tags: or方法in列表forindexifnot
3条回答

您的代码确实执行了您要它执行的操作(在简单的情况下):

>>> other_list = ['foo', 'bar    ', 'baz    ']
>>> filtered_list = [x for x in other_list
...                  if not '    ' in x or '    ' in other_list[int(other_list.index(x) -1)]]
>>> print filtered_list
['foo', 'baz    ']

即,它选择所有不包含四个空格的项,或者跟随一个不包含四个空格的项。

这在很多方面都是很奇怪的代码——例如,为什么在重复的情况下使用.index来选择第一个等于x的项;并且,第一个项是否应该像这段代码所说的那样被视为“跟随”最后一个项?但是,如果没有一个清晰的英文解释来解释你的代码应该完成什么,只是“逆向工程”所写的代码,它看起来确实在简单的情况下做了它所说的事情(第一项不包含四个空格,没有重复项),尽管非常,非常效率很低(O(N平方),其中用enumerate将其设为O(N)。

因此,请提供一个清晰、详尽的解释,说明你认为你在这里做了什么,我很乐意编辑这个答案,向你展示如何做你真正的意思,而不是你(显然是错误的)编码了什么。但是,我看不懂你的心思,所以。。。(顺便说一句,这确实需要是一个“答案”,因为格式化上面的代码对代码的可读性至关重要,所以它不能是“仅仅一个注释”)。

添加:通常的“在当前项目之前获取项目”的方式当然不会使用other_list(也就是O(N),这样可以使整个列表理解O(N squared)!)而是enumerate。什么是“前一项”第一项需要解释,但正常的阅读是“没有这样的东西”。

所以假设有两个函数curp(谓词限定当前项,如果truthy在它上面)和prevp(谓词限定当前项,如果truthy在上一个项上,如果有)。那么,从列表xs中选择项的正常方式显然是:

[x for i, x in enumerate(xs) if curp(x) or i>0 and prevp(xs[i-1])]

当然,无论谓词是否被优雅地封装到函数中(如上所述),或者更粗略地在线表示,它的工作方式都是完全相同的。因此,如果,例如:

def curp(x): return 'AB' not in x
def prevp(xp): return 'CD' in xp

然后,下面的listcomp与前面的listcomp等价,只是可读性较差:

[x for i, x in enumerate(xs) if 'AB' not in X or i>0 and 'CD' in xs[i-1]]

括号在这里是相当多余的,而且not 'AB' in X是一种更不优雅、可读性更强、更不含糊的表达方式'AB' not in X——但是,可以忽略这些风格观点,毕竟它们仅仅来自15年的Python经验:-)

我希望这能解决你的问题:

other_list = ['foo', 'bar    ', 'baz    ']
filtered_list = [x for x in other_list if ('    ' not in x) or ('    ' not in other_list[int(other_list.index(x) -1)])]
print filtered_list

注意:not的位置决定了命令的解释方式。我以为你想要这样的东西。

您可以使用多个ands/ors,但只能使用一个if。例如,以下内容:

In [7]: a = [1,2,3,4,5,6,7,8,9,10]

In [8]: b = [x for x in a if x % 2 == 0 or x % 3 == 0]

In [9]: b
Out[9]: [2, 3, 4, 6, 8, 9, 10]

工作得很好。

相关问题 更多 >