如何在列表推导中使用重新匹配对象

时间:2010-03-12 23:51:02

标签: python regex list-comprehension

我有一个函数从字符串列表中挑出块并将它们作为另一个列表返回:

def filterPick(lines,regex):
    result = []
    for l in lines:
        match = re.search(regex,l)
        if match:
            result += [match.group(1)]
    return result

有没有办法将此重新表述为列表理解?显然它是相当清楚的;只是好奇。


感谢那些贡献者,特别提到了@Alex。这是我最终得到的浓缩版本;正则表达式匹配方法作为“预先提升”参数传递给filterPick:

import re

def filterPick(list,filter):
    return [ ( l, m.group(1) ) for l in list for m in (filter(l),) if m]

theList = ["foo", "bar", "baz", "qurx", "bother"]
searchRegex = re.compile('(a|r$)').search
x = filterPick(theList,searchRegex)

>> [('bar', 'a'), ('baz', 'a'), ('bother', 'r')]

5 个答案:

答案 0 :(得分:69)

[m.group(1) for l in lines for m in [regex.search(l)] if m]

“技巧”是for m in [regex.search(l)]部分 - 这就是你如何“分配”一个你需要多次使用的值,在列表理解中 - 添加这样一个子句,其中对象“迭代“在包含您想要”分配“它的一个值的单项列表上。有些人认为这在风格上是可疑的,但有时我觉得它很实用。

答案 1 :(得分:10)

return [m.group(1) for m in (re.search(regex, l) for l in lines) if m]

答案 2 :(得分:7)

可以缩短一点

def filterPick(lines, regex):
    matches = map(re.compile(regex).match, lines)
    return [m.group(1) for m in matches if m]

你可以将它全部放在一行中,但这意味着你必须将每一行匹配两次才会效率低一些。

答案 3 :(得分:1)

Python 3.8开始,并引入assignment expressions (PEP 572):=运算符),可以在列表推导中使用局部变量,以避免多次调用同一表达式:

# items = ["foo", "bar", "baz", "qurx", "bother"]
[(x, match.group(1)) for x in items if (match := re.compile('(a|r$)').search(x))]
# [('bar', 'a'), ('baz', 'a'), ('bother', 'r')]

此:

  • re.compile('(a|r$)').search(x)的评估命名为变量match(可以是NoneMatch对象)
  • 在适当位置使用此match命名表达式(NoneMatch)来过滤不匹配的元素
  • 然后通过提取第一组(match)在映射值中重新使用match.group(1)

答案 4 :(得分:-14)

>>> "a" in "a visit to the dentist" 
True 
>>> "a" not in "a visit to the dentist" 
False

这也适用于您在列表中搜索的搜索查询

`P ='a','b','c'

P`中的

'b'返回true