Подтвердить что ты не робот

Re.findall, который возвращает dict названных групп захвата?

Вдохновленный теперь вопросом, который был удален; если задано регулярное выражение с именованными группами, существует ли метод findall, который возвращает список dict с именованными группами захвата вместо списка tuple?

Дано:

>>> 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'}]
4b9b3361

Ответ 1

>>> 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

вы можете переключиться на 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

Если вы используете совпадение:

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

документация здесь

Ответ 4

Нет встроенного метода для этого, но ожидаемый результат может быть достигнут с помощью использования списков.

[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).

Для каждого элемента в результате мы строим dict из другого понимания списка, которое генерируется из поля groupindex скомпилированного шаблона, который выглядит так:

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

Для каждого элемента в groupindex создается список, и если элемент из findall был кортежем, номер группы из groupindex используется для поиска правильного элемента, иначе элемент присваивается ( только сохранившаяся) именованная группа.

[k, i if isinstance(i, str) else i[v-1]]

Наконец, dict строит из списка списков строк.

Обратите внимание, что groupindex содержит только именованные группы, поэтому в результирующем dict не будут отображаться группы с неименованными захватами.

И результат:

[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'}]