Извлечение совпадений с исходным регистром, использованным в шаблоне, во время поиска без учета регистра - PullRequest
0 голосов
/ 10 марта 2020

При выполнении сопоставления с регулярным выражением мы получаем содержимое, которое было сопоставлено. Что если я хочу шаблон, который был найден в содержимом?

См. Приведенный ниже пример:

>>> import re
>>> r = re.compile('ERP|Gap', re.I)
>>> string = 'ERP is integral part of GAP, so erp can never be ignored, ErP!'
>>> r.findall(string)
['ERP', 'GAP', 'erp', 'ErP']

, но я хочу, чтобы вывод выглядел следующим образом: ['ERP', 'Gap', 'ERP', 'ERP']

Потому что, если я сгруппирую и суммирую исходный вывод, я получу следующий вывод в виде кадра данных:

ERP 1
erp 1
ErP 1
GAP 1
gap 1

Но что, если я хочу, чтобы вывод выглядел как

ERP 3
Gap 2

в соответствии с ключевыми словами, которые я ищу?

БОЛЬШЕ КОНТЕКСТА

У меня есть список ключевых слов, подобный этому: ['ERP', 'Gap']. У меня есть такая строка: "ERP, erp, ErP, GAP, gap"

Я хочу подсчитать, сколько раз каждое ключевое слово появлялось в строке. Теперь, если я выполняю сопоставление с шаблоном, я получаю следующий вывод: [ERP, erp, ErP, GAP, gap].

Теперь, если я хочу агрегировать и считать, я получаю следующий фрейм данных:

ERP 1
erp 1
ErP 1
GAP 1
gap 1

Пока я хочу, чтобы вывод выглядел так:

ERP 3
Gap 2

Ответы [ 2 ]

2 голосов
/ 10 марта 2020

Вы можете построить шаблон динамически, чтобы включить индексы слов, которые вы ищете, в названия групп, а затем получить те части шаблона, которые соответствуют:

import re

words = ["ERP", "Gap"]
words_dict = { f'g{i}':item for i,item in enumerate(words) } 

rx = rf"\b(?:{'|'.join([ rf'(?P<g{i}>{item})' for i,item in enumerate(words) ])})\b"

text = 'ERP is integral part of GAP, so erp can never be ignored, ErP!'

results = []
for match in re.finditer(rx, text, flags=re.IGNORECASE):
    results.append( [words_dict.get(key) for key,value in match.groupdict().items() if value][0] )

print(results) # => ['ERP', 'Gap', 'ERP', 'ERP']

См. Демонстрационную версию Python онлайн

Шаблон будет выглядеть как \b(?:(?P<g0>ERP)|(?P<g1>Gap))\b:

  • \b - граница слова
  • (?: - начало не захвата группа инкапсулирующих частей шаблона:
    • (?P<g0>ERP) - группа "g0": ERP
    • | - или
    • (?P<g1>Gap) - группа "g1": Gap
  • ) - конец группы
  • \b - граница слова.

См. regex demo .

Примечание [0] с [words_dict.get(key) for key,value in match.groupdict().items() if value][0] будет работать во всех случаях, поскольку при совпадении сопоставляется только одна группа.

0 голосов
/ 10 марта 2020

См. Комментарии выше. Попробуйте:

>>> [x.upper() for x in r.findall(string)]
['ERP', 'GAP', 'ERP', 'ERP']
>>>

ИЛИ

>>> map(lambda x: x.upper(), r.findall(string))
['ERP', 'GAP', 'ERP', 'ERP']
>>> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...