как получить шаблон, повторяющийся несколько раз в строке, используя регулярное выражение - PullRequest
1 голос
/ 29 сентября 2019

Я все еще новичок в регулярных выражениях, как в библиотеке Python re.

Я хочу извлечь все собственные существительные как целое слово, если они разделены пробелом.

Я пытался

result = re.findall(r'(\w+)\w*/NNP (\w+)\w*/NNP', tagged_sent_str)

Ввод: У меня есть строка типа

tagged_sent_str = "European/NNP Community/NNP French/JJ European/NNP export/VB" 

Ожидаемый вывод:

[('European Community'), ('European')]

Токовый выход:

[('European','Community')]

Но это даст только пары, а не одиночные.Я хочу все виды

Ответы [ 3 ]

1 голос
/ 29 сентября 2019

IIUC, itertools.groupby больше подходит для этого вида работы:

from itertools import groupby

def join_token(string_, type_ = 'NNP'):
    res = []
    for k, g in groupby([i.split('/') for i in string_.split()], key=lambda x:x[1]):
        if k == type_:
            res.append(' '.join(i[0] for i in g))
    return res

join_token(tagged_sent_str)

Выход:

['European Community', 'European']

и не требует изменений, если вы ожидаете три илибольше последовательных типов:

str2 = "European/NNP Community/NNP Union/NNP French/JJ European/NNP export/VB" 

join_token(str2)

Вывод:

['European Community Union', 'European']
0 голосов
/ 29 сентября 2019

Интересное требование.Код поясняется в комментариях, очень быстрое решение с использованием только REGEX:

import re
# make it more complex
text = "export1/VB European0/NNP export/VB European1/NNP Community1/NNP Community2/NNP French/JJ European2/NNP export/VB European2/NNP"


# 1: First clean app target words word/NNP to word,
#  you can use str.replace but just to show you a technique
# how to to use back reference of the group use \index_of_group
# re.sub(r'/NNP', '', text)
# text.replace('/NNP', '')
_text = re.sub(r'(\w+)/NNP', r'\1', text)

# this pattern strips the leading and trailing spaces
RE_FIND_ALL = r'(?:\s+|^)((?:(?:\s|^)?\w+(?=\s+|$)?)+)(?:\s+|$)'
print('RESULT : ', re.findall(RE_FIND_ALL, _text))

ВЫХОД:

  RESULT :  ['European0', 'European1 Community1 Community2', 'European2', 'European2']

Объяснение REGEX:

  • (?:\s+|^): пропустить начальные пробелы

  • ((?:(?:\s)?\w+(?=\s+|$))+): захватить группу без подгруппы Подгруппа (?:(?:\s)?\w+(?=\s+|$)) будет соответствовать всем последовательным словам, следующим за пробелами или концом строки.и этот матч будет зафиксирован глобальной группой.если мы не сделаем этого, совпадение вернет только первое слово.

  • (?:\s+|$): удалить завершающий пробел последовательности

Мне нужно было удалить /NNP из целевых слов, потому что вы хотите сохранить последовательность word/NNP в одной группе, делая что-то вроде этого (word)/NNP (word)/NPP, это вернет два элемента в одной группе, но не как один текст, поэтому, удалив его, текст будетбыть word word, поэтому REGEX ((?:\w+\s)+) будет захватывать последовательность слов, но это не так просто, потому что нам нужно захватить слово, которое не содержит /sequence_of_letter в конце, не нужно циклически повторять соответствующие группы, чтобыэлемент concatenate для создания корректного текста.

ПРИМЕЧАНИЕ : оба решения работают нормально, если все слова в этом формате word/sequence_of_letters;если у вас есть слова, которые не в этом формате, вы должны исправить это.Если вы хотите оставить их, добавьте /NPP в конце каждого слова, иначе добавьте /DUMMY, чтобы удалить их.

Используя re.split, но медленно, потому что я использую list comprehensive, чтобы исправить результат:

import re
# make it more complex
text = "export1/VB Europian0/NNP export/VB Europian1/NNP Community1/NNP Community2/NNP French/JJ Europian2/NNP export/VB Europian2/NNP export/VB export/VB"

RE_SPLIT = r'\w+/[^N]\w+'
result = [x.replace('/NNP', '').strip() for x in re.split(RE_SPLIT, text) if x.strip()]
print('RESULT:  ', result)    
0 голосов
/ 29 сентября 2019

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

tagged_sent_str = "European/NNP Community/NNP French/JJ European/NNP export/VB"                                      

[ re.sub(r"/NNP","",s) for s in re.findall(r"\w+/NNP(?:\s+\w+/NNP)*",tagged_sent_str) ]                               
['European Community', 'European']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...