这个问题是针对Python 3.6+(但对于其他读者,较低的Python可以随意回答)。
我想从每个与正则表达式匹配的字符串中提取一个子字符串。
说我有以下内容:
a = ['v-01-001', 'v-01-002', 'v-02-001', 'v-02-002', 'v-02-003', 'v-03-001']
我要匹配v-02-\d\d\d
的所有字符串的最后3位数字,即:
['001', '002', '003']
我天真的尝试:
[x[1] for x in list(map(lambda i: re.search(r'v-02-(\d\d\d)', i), a)) if x]
您能提出更优雅的方法吗?
谢谢
答案 0 :(得分:1)
您可以执行以下操作:
import re
a = ['v-01-001', 'v-01-002', 'v-02-001', 'v-02-002', 'v-02-003', 'v-03-001']
pattern = re.compile('v-02-(\d{3})$')
print([m.group(1) for m in map(pattern.match, a) if m])
输出
['001', '002', '003']
还可以使用finditer
:
print([m.group(1) for ms in map(pattern.finditer, a) for m in ms])
输出
['001', '002', '003']
答案 1 :(得分:1)
四种方法。
第一个只是常规的'ole循环:
li=[]
for s in a:
m = re.search(r'v-02-(\d\d\d)', s)
if m:
li.append(m.group(1))
# li=['001', '002', '003']
第二次在列表理解中调用同一正则表达式:
>>> [re.search(r'v-02-(\d\d\d)', s).group(1) for s in a if re.search(r'v-02-(\d\d\d)', s)]
['001', '002', '003']
第三种是使用map
:
>>> [m.group(1) for m in map(lambda s: re.search(r'v-02-(\d\d\d)', s), a) if m]
['001', '002', '003']
最后,您可以使用.join
整理列表,然后使用findall
:
>>> re.findall(r'\bv-02-(\d\d\d)\b', '\t'.join(a))
['001', '002', '003']
或者,使用\n
和re.M
与两个\b
:
>>> re.findall(r'^v-02-(\d\d\d)$', '\n'.join(a), flags=re.M)
['001', '002', '003']
如果我编写这段代码,我可能会以相同的顺序编写。
我认为在旁观者眼中,什么是更优雅。我认为最后一个会更优雅。
您还可以跳过正则表达式并使用Python的字符串方法:
>>> prefix='v-02-'
>>> [e[len(prefix):] for e in filter(lambda s: s.startswith(prefix),a)]
['001', '002', '003']
在这种情况下,这可能是最快的 。
2019年12月,将会有更多优雅替代方案。根据{{3}}中的定义,您将能够使用赋值语句,以便您可以分配匹配并一步测试该匹配:
[m.group(1) for s in a if (m:=re.search(r'v-02-(\d\d\d)', s))]