我试图将这个工作嵌套的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)]
关于如何解决这个问题的任何指示?
答案 0 :(得分: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 ]
答案 1 :(得分: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]
请注意,我在这里使用生成器表达式:它们与列表推导基本相同,但不要将完整结果创建为列表,而是一次只生成元素。因此,如果您只想逐个使用它(这是这种情况),它会更有效率。毕竟,你只对列表推导的结果感兴趣,所以理解将消耗生成器表达式。
答案 2 :(得分: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)]