Regex python: возвращать слова, окружающие персонажа - PullRequest
0 голосов
/ 17 мая 2018

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

string = 'I have a sentence with $10.00 within it and this sentence is done. '

Я бы хотел, чтобы регулярное выражение вернуло

surrounding = ['I', 'have', 'a', 'sentence', 'with', 'within', 'it', 'and', 'this', 'sentence']

Моя конечная цель состоит в подсчете всех слов, которые окружают упоминание о '$', так чтоПриведенный выше список будет дополнен:

final_return = [('I', 1), ('have', 1), ('a', 1), ('sentence', 2), ('with', 1), ('within', 1), ('it', 1), ('and', 1), ('this', 1)]

Приведенное ниже регулярное выражение, которое я разработал, может вернуть строку, присоединенную к символу валюты, с окружающими ее 5 символами.Есть ли способ отредактировать регулярное выражение вместо пяти окружающих слов?Должен ли я (и если да, то как) использовать токенизатор NLTK для достижения этой цели?

   import re
 .....\$\s?\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{1,2})?.....

Ответы [ 4 ]

0 голосов
/ 17 мая 2018

Используйте разделение для разделения слов, удалите не слово с исальфой, а затем подсчитайте частоту слова в списке.

string='I have a sentence with $10.00 within it and this sentence is done. '
string1=string.split()
string2=[s for s in string1 if s.isalpha()]
[[x,string2.count(x)] for x in set(string2)] 
#[['and', 1], ['within', 1], ['sentence', 2], ['it', 1], ['a', 1], ['have', 1], ['with', 1], ['this', 1], ['is', 1], ['I', 1]]
0 голосов
/ 17 мая 2018

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

В этом случае вы можете использовать collections.deque(), который представляет собой правильную структуру данных с ограниченным количеством элементов для сохранения пяти предыдущих слов. Затем вы можете использовать объект collections.Counter() для возврата счетчика слов в пределах порога.

from collections import deque
from collections import Counter
from itertools import chain

def my_counter(string):
    container = deque(maxlen=5)
    words = iter(string.split())
    def next_five(words):
        for _ in range(5):
            try:
                yield next(words)
            except StopIteration:
                pass

    for w in words:
        if w.startswith('$'):
            yield Counter(chain(container, next_five(words)))
        else:
            container.append(w)

Демо-версия:

In [8]: s =  ' extra1 extra2 I have a sentence with $10.00 within it and this sentence is done.asdf asdf a b c d e $5 k j n m k gg ee'

In [9]: 

In [9]: list(my_counter(s))
Out[9]: 
[Counter({'I': 1,
          'a': 1,
          'and': 1,
          'have': 1,
          'it': 1,
          'sentence': 2,
          'this': 1,
          'with': 1,
          'within': 1}),
 Counter({'a': 1,
          'b': 1,
          'c': 1,
          'd': 1,
          'e': 1,
          'j': 1,
          'k': 2,
          'm': 1,
          'n': 1})]
0 голосов
/ 17 мая 2018

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

(?P<before>(?:\w+\W+){5})
\$\d+(?:\.\d+)?
(?P<after>(?:\W+\w+){5})

См. демо на regex101.com .


In Python:
from collections import Counter
import re

rx = re.compile(r'''
    (?P<before>(?:\w+\W+){5})
    \$\d+(?:\.\d+)?
    (?P<after>(?:\W+\w+){5})
    ''', re.VERBOSE)

sentence = 'I have a sentence with $10.00 within it and this sentence is done. '
words = [Counter(m.group('before').split() + m.group('after').split())
                    for m in rx.finditer(sentence)]
print(words)


Это дает (обратите внимание, что Counter уже dict):
[Counter({'sentence': 2, 'I': 1, 'have': 1, 'a': 1, 'with': 1, 'within': 1, 'it': 1, 'and': 1, 'this': 1})]
0 голосов
/ 17 мая 2018

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

import re

string = 'I have a sentence with $10.00 within it and this sentence is done. '

surrounding  = re.search(r'(\w+)\s*(\w+)\s*(\w+)\s*(\w+)\s*(\w+)\s*\$\d+\.?\d{2}?\s*(\w+)\s*(\w+)\s*(\w+)\s*(\w+)\s*(\w+)', string, flags=0).groups()

print(surrounding )
...