列表理解中的“如果...或......”语句?

时间:2014-12-26 02:17:26

标签: python python-3.x list-comprehension

在Python 3.4.2中,有没有办法让#34; 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"

有办法做到这一点吗? A" for"循环会更容易阅读,但我试图推动我对列表理解的理解。提前谢谢。

(奇怪的是,我无法在stackoverflow上找到像这样的先前问题。)

4 个答案:

答案 0 :(得分:8)

您的代码确实完全按照您的要求执行操作(在简单情况下):

>>> 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之前获取当前项目的正常方式”当然使用.indexO(N)所以使整个列表理解O(N squared)!)而是enumerate。什么是“之前的项目”第一个需要解释,但正常的读数是“没有这样的东西”。

假设您有两个函数curp(谓词限定当前项目,如果它是真实的)和prevp(谓词限定当前项目,如果在上一个 item if any )。然后,从列表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等同于前一个,只是不太可读:

[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体验: - )

答案 1 :(得分:2)

您可以使用多个and s / or,但只能使用一个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]

工作正常。

答案 2 :(得分:0)

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

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

注意:该位置不确定如何解释命令。我以为你想要这样的东西。

答案 3 :(得分:0)

Yikes我刚刚意识到我的错误写了我的例子。我想切换if和for语句:

filtered_list = [x
                 if not '    ' in x or '    ' in other_list[int(other_list.index(x) -1)]
                 for x in other_list]

我会发布我的整个列表理解,以便按照这个顺序显示我为什么要这样做。基本上,我有一个包含一些缩进项目的列表。对于每个缩进项目,我想将其缩进加倍并在其前缩进项目,同时保持列表中其余项目不变。

indented_list = [t
                 if not '    ' in t or '    ' in stripped_list[int(stripped_list.index(t) + 1)]
                    else ''.join(('    ', t))
                    if not t[0].isdigit()
                        else re.sub(r'^(\d)(.*)', r'\1\2   \3',
                                    stripped_list[int(stripped_list.index(t))])
                        if not t[1].isdigit()
                            else re.sub(r'^(\d)(\d)(.*)', r'\1\2  \3',
                                        stripped_list[int(stripped_list.index(t))])
                 for t in stripped_list]

我知道可能更容易实现这一目标。几周前我才开始学习编程。