Найдите существительную фразу до и после числа в тексте
Учитывая текст, я должен найти предыдущие слова для всех чисел до стоп-слова, принадлежащего списку check_words (вид стоп-слов).
Мой код:
check_words = ['the', 'a', 'with','to']
mystring = 'the code to find the beautiful words 78 that i have to nicely check 45 with the snippet'
list_of_words = mystring.split()
В этом конкретном тексте я бы проверил раньше '78'
и '45'
вернусь назад до точки, где я найду любое из слов в check_words (но не более 8 слов).
Код для этого может быть:
preceding_chunks = []
for i,word in enumerate(list_of_words):
if any(char.isdigit() for char in word):
# 8 precedent words (taking into account that I can not slice with 8 back at the beginning)
preceding_words = list_of_words[max(0,i-8):i]
preceding_words[::-1]
# I check from the end of the list towards the start
for j,sub_word in enumerate(preceding_words[::-1]):
if sub_word in check_words:
# printing out j for checking
myposition = j
print(j)
real_preceding_chunk = preceding_words[len(preceding_words)-j:]
print(real_preceding_chunk)
preceding_chunks.append(real_preceding_chunk)
break
Этот код работает. в основном я проверяю каждое слово, но у меня сложилось впечатление (возможно, я ошибаюсь), что этого можно добиться с помощью пары одинарных вкладышей и, следовательно, без петель. Есть идеи?
ПРИМЕЧАНИЕ. Этот вопрос касается улучшения читаемости кода, попыток избавиться от циклов, чтобы сделать код быстрее, и попыток сделать код лучше, что является частью дзен Python.
ПРИМЕЧАНИЕ 2: Некоторые предыдущие проверки, которые я сделал:
- Поиск позиции элемента в другом списке из числа в другом списке
- Поиск индекса элемента в списке
- Найти в списке
Ответы
Я придумал это:
import itertools
import re
chunks = (grouped_chunk.split() for grouped_chunk in re.split("\\s+\\d+\\s+", mystring))
preceding_chunks = []
for reversed_chunk in map(reversed, chunks):
preceding_chunk = list(itertools.takewhile(lambda word: word not in check_words, reversed_chunk))[::-1]
preceding_chunks.append(preceding_chunk)
Мы применяем itertools.takewhile
к, reversed_chunk
который дает нам предыдущий кусок в обратном порядке. Затем мы получаем правильно упорядоченный preceding_chunk
, переставляя в конце с [::-1]
.
Регулярное выражение разбивается mystring
на основе числа (экранированного \d+
). Окружающие экранированные символы \s+
s представляют собой любые отступы вокруг числа. Это приводит к тому, что этот код ведет себя иначе, чем ваш, если цифры и буквы смешиваются в одних и тех же словах (например, a1
).
Для вашего исходного кода я бы сделал пару предложений:
- Следуйте PEP 8 . Например, добавьте интервал после запятой в
i,word
. - Удалите лишнее выражение
preceding_words[::-1]
. Хотя это оценивается как обратноеpreceding_words
, потому что оно не на месте, оценка не имеет побочных эффектов. Кроме того, вы уже выполняете этот разворот вenumerate(preceding_words[::-1])
.