问题描述
我正在尝试将此工作嵌套的forloop转换为单行列表理解&我似乎无法使其正常工作。 伪代码如下:
result = []
for x in something:
for y in x.address:
m = re.search("some pattern to match",y)
if m:
result += [m.group(1)]
关于如何解决这个问题的任何指示?
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 ]
2楼
嵌套循环并不是列表理解的真正问题,因为您也可以将其嵌套在其中:
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)]
但这显然会两次运行您通常希望避免的搜索。 在这一点上,您可以使用一些我通常不建议使用的骇人听闻的解决方案(因为它们会损害可读性)。 由于您的结果仅取决于正则表达式搜索的结果,因此您还可以分两个步骤解决此问题:首先,搜索每个元素并将它们映射到match对象,然后对那些匹配项进行过滤并只返回有效的那些:
[m.group(1) for m in (rexpr.search(y) for x in something for y in x.address) if m]
请注意,我在这里使用生成器表达式:这些表达式基本上与列表推导相同,但不会将完整结果创建为列表,而是一次仅在元素上屈服。 因此,如果您只想一一消耗(在这种情况下),则效率更高。 毕竟,您只对列表推导的结果感兴趣,因此推导将消耗生成器表达式。
3楼
我会做这样的事情:
# 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)]