re.findall返回一个命名捕获组的字典?

80

受已删除的问题启发; 给定一个带有命名组的正则表达式,是否有类似于findall的方法,它返回一个字典列表,其中包含命名捕获组,而不是元组列表?

给定:

>>> import re
>>> text = "bob sue jon richard harry"
>>> pat = re.compile('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)')
>>> pat.findall(text)
[('bob', 'sue'), ('jon', 'richard')]

应该改为:

[{'name': 'bob', 'name2': 'sue'}, {'name': 'jon', 'name2': 'richard'}]
4个回答

157

使用 Pattern.finditer() 然后 Match.groupdict()

>>> import re
>>> s = "bob sue jon richard harry"
>>> r = re.compile('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)')
>>> [m.groupdict() for m in r.finditer(s)]
[{'name2': 'sue', 'name': 'bob'}, {'name2': 'richard', 'name': 'jon'}]

2
这是一个比我的版本更好的解决方案,我的版本主要依赖于一开始使用findall - beerbajay

15

你可以切换到使用finditer。

>>> import re
>>> text = "bob sue jon richard harry"
>>> pat = re.compile('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)')
>>> for m in pat.finditer(text):
...     print m.groupdict()
... 
{'name2': 'sue', 'name': 'bob'}
{'name2': 'richard', 'name': 'jon'}

9

如果您正在使用match:

r = re.match('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)', text)
r.groupdict()

请参考此处的文档

1
Match只会找到一个匹配项,而不是所有的匹配项。 - Björn Lindqvist

1

没有内置的方法可以完成这个任务,但可以使用列表推导式来获得期望的结果。

[dict([[k, i if isinstance(i, str) else i[v-1]] for k,v in pat.groupindex.items()]) for i in pat.findall(text)]

带有友好格式:

>>> [
...     dict([
...         [k, i if isinstance(i, str) else i[v-1]]
...         for k,v in pat.groupindex.items()
...     ])
...     for i in pat.findall(text)
... ]

我们使用列表推导式构建一个列表,迭代来自findall的结果,该结果是字符串列表或元组列表(0或1个捕获组的结果为str列表)。

对于结果中的每个项目,我们从编译模式的groupindex字段生成另一个列表推导式构建一个dict,它看起来像:

>>> pat.groupindex
{'name2': 2, 'name': 1}

针对groupindex中的每个项目构建一个列表,如果findall中的项目是元组,则使用来自groupindex的组编号查找正确的项目,否则该项目将被分配给(唯一存在的)命名组。
[k, i if isinstance(i, str) else i[v-1]]

最后,从字符串列表的列表中构建了一个字典。
请注意,groupindex 仅包含命名组,因此未命名的捕获组将从结果字典中省略。
最终结果为:
[dict([[k, i if isinstance(i, str) else i[v-1]] for k,v in pat.groupindex.items()])  for i in pat.findall(text)]
[{'name2': 'sue', 'name': 'bob'}, {'name2': 'richard', 'name': 'jon'}]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接