Используйте регулярное выражение для поиска через модуль re
. Механизм регулярных выражений может обрабатывать соответствующие элементы в поиске по тексту намного лучше, чем вложенный цикл for
.
Я собираюсь использовать более подходящие имена переменных, чтобы было понятнее, куда должен идти список; titles
- это названия стихотворений, которые вы просматриваете, и names
то, что вы пытаетесь сопоставить. matched
- это пары (title, name)
, которые вы хотите создать:
import re
titles = ["happy new year", "game over", "a happy story", "hold on"]
names = ["happy", "new", "hold"]
by_reverse_length = sorted(names, key=len, reverse=True)
pattern = "|".join(map(re.escape, by_reverse_length))
any_name = re.compile("({})".format(pattern))
matches = []
for title in titles:
for match in any_name.finditer(title):
matches.append((title, match.group()))
Приведенный выше выводит требуемый результат:
>>> matches
[('happy new year', 'happy'), ('happy new year', 'new'), ('a happy story', 'happy'), ('hold on', 'hold')]
Имена сортируются по длине, в обратном порядке, так что более длинные имена находятся перед более короткими с тем же префиксом; например Hollander
найдено до Holland
найдено до Holl
.
Строка pattern
создается из ваших имен для формирования шаблона ...|...|...
альтернатив , любой из этих шаблонов может совпадать, но механизм регулярных выражений найдет перечисленные ранее в последовательности над этими. поставить позже, отсюда необходимость обратной сортировки по длине. (...)
круглые скобки вокруг всего шаблона имен говорят механизму регулярных выражений захватывать этой части текста в группе. Вызов match.group()
в цикле может затем извлечь сопоставленный текст.
Функция *1034*re.escape()
предназначена для предотвращения «метасимволов» в именах, символов со специальным значением, таких как ^
, $
, (
, )
и т. Д. от интерпретации как их специальные значения регулярных выражений.
Функция re.finditer()
(и метод для скомпилированных шаблонов) затем находит непересекающиеся совпадения по порядку слева направо, поэтому она никогда не будет соответствовать более коротким подстрокам и дает нам возможность извлечь соответствует объекту для каждого. Это дает вам больше возможностей, если вы хотите знать о начальных позициях совпадений , а также о других метаданных, если они вам нужны. В противном случае re.findall()
также может быть использовано здесь.
Если вы собираетесь использовать вышеприведенный текст с западными алфавитами , а не на китайском, то, возможно, вы также захотите добавить маркеры границы слова \b
:
any_name = re.compile("\b({})\b".format(pattern))
в противном случае подстроки могут быть сопоставлены с частью большего слова. Поскольку в китайском языке нет символов границы слов (таких как пробелы и знаки препинания), вы не хотите использовать \b
в таких текстах.