Bre*_*ugh 41 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
Run Code Online (Sandbox Code Playgroud)
有没有办法将其重新表述为列表理解?显然它是相当清楚的; 只是好奇.
感谢那些贡献的人,特别提到了@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')]
Run Code Online (Sandbox Code Playgroud)
Ale*_*lli 70
[m.group(1) for l in lines for m in [regex.search(l)] if m]
Run Code Online (Sandbox Code Playgroud)
"技巧"是for m in [regex.search(l)]部分 - 这就是你如何"分配"一个你需要在列表理解中多次使用的值 - 添加这样一个子句,其中对象"迭代"在单项列表上包含您要"分配"它的一个值.有些人认为这在风格上是可疑的,但我觉得它有时候很实用.
Ign*_*ams 10
return [m.group(1) for m in (re.search(regex, l) for l in lines) if m]
Run Code Online (Sandbox Code Playgroud)
它可以缩短一点
def filterPick(lines, regex):
matches = map(re.compile(regex).match, lines)
return [m.group(1) for m in matches if m]
Run Code Online (Sandbox Code Playgroud)
你可以将它全部放在一行中,但这意味着你必须匹配每一行两次,效率会有点低.
开始Python 3.8,并引入赋值表达式(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')]
Run Code Online (Sandbox Code Playgroud)
这:
re.compile('(a|r$)').search(x)为变量match(要么是None一个Match对象)match就地使用此命名表达式(None或者 a Match)来过滤掉不匹配的元素match映射值match.group(1)。