Ответ 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'}]
Вдохновленный теперь вопросом, который был удален; если задано регулярное выражение с именованными группами, существует ли метод 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'}]
>>> 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'}]
вы можете переключиться на 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'}
Если вы используете совпадение:
r = re.match('(?P<name>[a-z]+)\s+(?P<name2>[a-z]+)', text)
r.groupdict()
Нет встроенного метода для этого, но ожидаемый результат может быть достигнут с помощью использования списков.
[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'}]