从字符串列表中获取子字符串列表,其中子字符串与某个正则表达式匹配

时间:2018-10-10 15:07:38

标签: python regex list-comprehension

这个问题是针对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]

您能提出更优雅的方法吗?

谢谢

2 个答案:

答案 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']

或者,使用\nre.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))]