Inspired by a now-deleted question; given a regex with named groups, is there a method like findall
which returns a list of dict
with the named capturing groups instead of a list of tuple
?
受到一个现在被删除的问题的启发;给定一个带命名组的regex,是否有像findall这样的方法,它返回带有命名捕获组的dict列表,而不是tuple列表?
Given:
考虑到:
>>> 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')]
Should instead give:
应该给:
[{'name': 'bob', 'name2': 'sue'}, {'name': 'jon', 'name2': 'richard'}]
4 个解决方案
#1
71
>>> 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
9
you could switch to finditer
你可以切换到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'}
#3
3
If you are using match :
如果您正在使用match:
r = re.match('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)', text)
r.groupdict()
文件在这里
#4
1
There's no built-in method for doing this, but the expected result can be achieved by using list comprehensions.
没有内置的方法来实现这一点,但是通过使用列表理解可以实现预期的结果。
[dict([[k, i if isinstance(i, str) else i[v-1]] for k,v in pat.groupindex.items()]) for i in pat.findall(text)]
With friendly formatting:
和友好的格式:
>>> [
... dict([
... [k, i if isinstance(i, str) else i[v-1]]
... for k,v in pat.groupindex.items()
... ])
... for i in pat.findall(text)
... ]
We construct a list using a list comprehension, iterate over the result from findall
which is either a list of strings or a list of tuples (0 or 1 capturing groups result in a list of str
).
我们使用列表理解构造一个列表,遍历findall的结果,它要么是字符串列表,要么是元组列表(0或1捕获组导致str列表)。
For each item in the result we construct a dict
from another list comprehension which is generated from the groupindex
field of the compiled pattern, which looks like:
对于结果中的每一项,我们从另一个列表理解中构造一条命令,这个理解来自编译模式的groupindex字段,它看起来如下:
>>> pat.groupindex
{'name2': 2, 'name': 1}
A list is constructed for each item in the groupindex
and if the item from findall
was a tuple, the group number from groupindex
is used to find the correct item, otherwise the item is assigned to the (only extant) named group.
为groupindex中的每个项构造一个列表,如果findall中的项是一个元组,则使用groupindex中的组号来查找正确的项,否则该项被分配给(仅存在的)命名组。
[k, i if isinstance(i, str) else i[v-1]]
Finally, a dict is constructed from the list of lists of strings.
最后,一个命令由字符串列表组成。
Note that groupindex
contains only named groups, so non-named capturing groups will be omitted from the resulting dict
.
注意groupindex只包含已命名的组,因此在生成的命令中将忽略未命名的捕获组。
And the result:
结果:
[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'}]
#1
71
>>> 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
9
you could switch to finditer
你可以切换到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'}
#3
3
If you are using match :
如果您正在使用match:
r = re.match('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)', text)
r.groupdict()
文件在这里
#4
1
There's no built-in method for doing this, but the expected result can be achieved by using list comprehensions.
没有内置的方法来实现这一点,但是通过使用列表理解可以实现预期的结果。
[dict([[k, i if isinstance(i, str) else i[v-1]] for k,v in pat.groupindex.items()]) for i in pat.findall(text)]
With friendly formatting:
和友好的格式:
>>> [
... dict([
... [k, i if isinstance(i, str) else i[v-1]]
... for k,v in pat.groupindex.items()
... ])
... for i in pat.findall(text)
... ]
We construct a list using a list comprehension, iterate over the result from findall
which is either a list of strings or a list of tuples (0 or 1 capturing groups result in a list of str
).
我们使用列表理解构造一个列表,遍历findall的结果,它要么是字符串列表,要么是元组列表(0或1捕获组导致str列表)。
For each item in the result we construct a dict
from another list comprehension which is generated from the groupindex
field of the compiled pattern, which looks like:
对于结果中的每一项,我们从另一个列表理解中构造一条命令,这个理解来自编译模式的groupindex字段,它看起来如下:
>>> pat.groupindex
{'name2': 2, 'name': 1}
A list is constructed for each item in the groupindex
and if the item from findall
was a tuple, the group number from groupindex
is used to find the correct item, otherwise the item is assigned to the (only extant) named group.
为groupindex中的每个项构造一个列表,如果findall中的项是一个元组,则使用groupindex中的组号来查找正确的项,否则该项被分配给(仅存在的)命名组。
[k, i if isinstance(i, str) else i[v-1]]
Finally, a dict is constructed from the list of lists of strings.
最后,一个命令由字符串列表组成。
Note that groupindex
contains only named groups, so non-named capturing groups will be omitted from the resulting dict
.
注意groupindex只包含已命名的组,因此在生成的命令中将忽略未命名的捕获组。
And the result:
结果:
[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'}]