Как комментирует пользователь Martineau, лучше всего профилировать код, чтобы определить, где оптимизация будет наиболее эффективной, и измерить эффект от любых попыток оптимизации.
При отсутствии каких-либо данных профилирования лучший кандидат наоптимизация, вероятно, будет следующим внутренним циклом:
for eachcity in allCities:
eachcity=eachcity.strip()
if re.search('\\b'+eachcity+'\\b',description,re.IGNORECASE):
citiesFound.add(eachcity)
Здесь код вызывает strip
для каждой строки в allCities
- что-то, что можно сделать только один раз, вне цикла, затем вызвать re.search
для каждого города.
Может оказаться более эффективным объединить все города в одно регулярное выражение, используя метасимвол |
, который обозначает альтернативные совпадения.Например, шаблон
r'foo|bar'
будет соответствовать 'foo'
или 'bar'
.
Вот простой пример:
>>> text = 'I am flying from les Escaldas to Dubai via Sharjah on Monday'
>>> cities = ['Sharjah', 'Dubai', 'les Escaldas', 'Ar Ruways']
>>> pattern = r'|'.join(r'\b{}\b'.format(re.escape(city)) for city in cities)
>>> pattern
'\\bSharjah\\b|\\bDubai\\b|\\bles Escaldas\\b|\\bAr Ruways\\b'
>>> matches = re.findall(pattern, text)
>>> print(matches)
['les Escaldas', 'Dubai', 'Sharjah']
Вызовre.escape
для каждого названия города предотвращает изменение шаблона поиска, если одно из названий городов содержит символ, который также является метасимволом регулярного выражения.
Применение этой техники к коду в вопросе:
# We only need to create the regex pattern once,
# so do it outside the loop.
pattern = r'|'.join(r'\b{}\b'.format(re.escape(city.strip())) for city in allCities)
for eachRow in descriptions_reader:
Sr_Num = eachRow['Sr_Num']
description = eachRow['Text']
citiesFound = set()
found = re.findall(pattern, description, re.IGNORECASE)
citiesFound.update(found)
matches = len(found)
Поведение метасимвола |
описано в документации .
RE, разделенные '|'пробуются слева направо.Когда один шаблон полностью совпадает, эта ветвь принимается.Это означает, что после совпадения A, B больше не будет проверяться, даже если это приведет к большему совпадению.
Таким образом, если есть потенциальные совпадения, которые являются подстроками других кандидатов - таких как «Дубай» и «Дубай Сити» - более длинный кандидат должен появиться раньше в шаблоне, в противном случае движок найдет более короткий ивернуть его как совпадение.
Чтобы предотвратить это, перед созданием шаблона сортируйте allCities
в порядке убывания длины:
allCities.sort(key=len, reverse=True)
или используйте sorted
если порядок allCities
должен быть сохранен:
pattern = r'|'.join(r'\b{}\b'.format(re.escape(city.strip())) for
city in sorted(allCities, key=len, reverse=True))