2015-10-19 113 views
0

我想这个工作嵌套的for循环转换成单行列表理解&我似乎无法得到它的工作。伪代码如下:Python的嵌套for循环列表理解

result = [] 
for x in something: 
    for y in x.address: 
     m = re.search("some pattern to match",y) 
     if m: 
     result += [m.group(1)] 

任何指针我如何去做这件事?

+0

那么,是的列表理解?它怎么不起作用?那究竟是什么问题? – Kasramvd

+1

是'if'应该在'for'块还是不在? – Kevin

+0

它应该在块内。对于错字。 – hmmm

回答

1

你需要一台发电机表达..

matches = (re.search(r'some pattern to match', y) for x in something 
                for y in x.address ) 
result = [ m.group(1) for m in matches if m ] 
+0

感谢reply.Just好奇 - 为什么这里需要一台发电机体现在哪里?假设我没有模式匹配语句,我都可以在一行中工作。 – hmmm

+0

因为您不能将re.search的结果作为列表理解语法的一部分存储到变量中。 –

+0

谢谢,这似乎工作。过去我没有使用过发生器在任何地方使用发生器。那么我会详细阅读它。谢谢 ! – hmmm

0

我会做这样的事情:

# match function 
def match(x): 
    m = re.search("some pattern to match",x) 
    if m: 
     return m.group(1) 
    else: 
     return None 

#list comprehension  
results = [match(y) for x in something for y in x.address if match(y)]  
+2

这对每个元素运行'match()'两次*。 – poke

+0

是的。不适合长长的名单,但简洁。 – zach

1

嵌套循环是不是真的列表理解问题,因为你可以嵌套这些也有:

lst = [] 
for y in z: 
    for x in y: 
     lst.append(f(x)) 

这个翻译成以下列表理解:

[f(x) for y in z for x in y] 

而且你可以很容易地继续多层次。

条件决定是否要的东西添加到列表或不是也工作得很好:

lst = [] 
for x in y: 
    if t(x): 
     lst.append(f(x)) 

这翻译成一个过滤器下面的列表理解:

[f(x) for x in y if t(x)] 

中当然你也可以把它和多个层次结合起来。


现在什么某种问题的,虽然是当你要首先执行的东西,那么就这个结果进行过滤,并追加的东西,要看结果。天真的解决办法是回到屋里去的函数调用,并做两次:

rexpr = re.compile('some pattern to match') 
[rexpr.search(y).group(1) for x in something for y in x.address if rexpr.search(y)] 

但这显然运行两次搜索,你通常希望避免的。在这一点上,你可以使用一些我通常不会推荐的hackish解决方案(因为它们会损害可读性)。由于你的结果只依赖于正则表达式搜索的结果,你也可以分两步解决这个问题:首先,搜索每一个元素,并将它们映射到一个匹配对象,那么你对这些比赛进行过滤,就回到有效的:

[m.group(1) for m in (rexpr.search(y) for x in something for y in x.address) if m] 

请注意,我在这里使用生成器表达式:这些都是基本相同的列表理解,但不创建完整的结果列表,但只有在时间因素上屈服。所以如果你只想一个接一个地消费(这里就是这种情况),效率会更高。毕竟,你只对列表理解的结果感兴趣,所以理解会消耗生成器表达式。

+0

感谢您的详细解释。看起来我真正需要的是Generators和感谢用例。 – hmmm