v0.0.39: оптимизация apply_replacements — однопроходная замена вместо N×re.sub (ускорение в разы)
Deploy drhider / validate (push) Canceled after 0s

This commit is contained in:
“Naeel”
2026-08-19 09:47:16 +04:00
parent e548c89880
commit bc09ada90e
3 changed files with 79 additions and 12 deletions
+33 -11
View File
@@ -55,23 +55,45 @@ def apply_replacements(text: str, mapping: Dict[str, str], sorted_keys: List[str
"""
result = text
# ── Однопроходная замена: единый regex из всех ключей ──
# Вместо N отдельных re.sub по всему тексту (O(N×text)) собираем
# один паттерн из всех ключей и делаем один re.sub с callback (O(text)).
if not sorted_keys:
return result
alternatives = []
for original in sorted_keys:
replacement = mapping[original]
# Если сущность обрамлена буквами/цифрами — используем границы слова
if original and original[0].isalnum() and original[-1].isalnum():
pattern = r'(?<!\w)' + re.escape(original) + r'(?!\w)'
if not original:
continue
esc = re.escape(original)
# Границы слова — только если сущность обрамлена буквами/цифрами
if original[0].isalnum() and original[-1].isalnum():
alternatives.append(r'(?<!\w)' + esc + r'(?!\w)')
else:
pattern = re.escape(original)
alternatives.append(esc)
new_result = re.sub(pattern, replacement, result)
if not alternatives:
return result
# Фоллбэк: Markdown-жирность могла разорвать строку
combined = re.compile('|'.join(alternatives))
matched_keys = set()
def _replace(match):
m = match.group(0)
matched_keys.add(m)
return mapping.get(m, m)
result = combined.sub(_replace, result)
# ── Фоллбэк: Markdown-жирность могла разорвать строку ──
# Применяется только к ключам, которые основная замена НЕ нашла
# (например, «ООО **"**НУБЕС**"» — ** внутри сущности).
for original in sorted_keys:
if not original or original in matched_keys:
continue
md_pattern = _md_tolerant_pattern(original)
if md_pattern is not None:
new_result = re.sub(md_pattern, replacement, new_result)
result = new_result
result = re.sub(md_pattern, mapping[original], result)
return result