python - 在 Python 中使用原子分组的最佳方式?
问题描述
所以我写了这个,这太可怕了:
def parse_results(string):
space = r"([\s\t]{0,5})"
building_type = r"(([Uu]nit|[Ss]tudio|[Ff]lat)?)"
street_type = (r"((\d+)(\&|\-)*(\d*)(\w*)(\w*)(\s*)(\w*)(\s*)(\w*)(\s*)"
r"([Ee]nd|[Gg]reen|[Cc]auseway|[Cc]heapside|[Cc]rescent|"
r"[Ss]treet|[Ll]ane|[Ww]alk|[Rr]oad|[Aa]venue|[Dd]rive|"
r"[Pp]ark|[Ww]ay|[Pp]lace|[Pp]arade|[Ii]ndustrial"
r"[Ee]state|[Tt]rading [Ee]state|[Hh]ouse|[Gg]reen))")
line_1 = r"(\w*)"
line_2 = r"(\w*)"
line_3 = r"(\w*)"
line_4 = r"(\w*)"
line_5 = r"(\w*)"
postcode = r"(([A-Z0-9][A-Z0-9][A-Z0-9]?[A-Z0-9]? {1,2}[0-9][A-Z]{2}))"
pattern = re.compile(rf"({building_type}{space}{street_type}{space}"
rf"{line_1}{space}{line_2}{space}{line_3}{space}"
rf"{line_4}{space}{line_5}{space}{postcode})")
try:
matches = pattern.finditer(string)
for match in matches:
address = re.sub(r"\s+", r" ", match.group(1))
return address
except Exception as e:
return (f"Error looking for address, exception {e}")
它的目的是在我用于机器学习培训的大型文本语料库中寻找英国地址。然而,由于回溯,它非常缓慢。
经过研究,解决方案似乎是使用原子分组,类似于在 Ruby 中完成的方式。
Python RE 模块不支持开箱即用,但是有一些解决方法,例如:
显然,有一个 Python Regex模块确实支持开箱即用的 atomix 分组,但几乎没有人在教程中谈论它。
两个问题:
哪个是最好的方法?RE 模块变通还是 Regex 模块?
有人可以指出示例的方向,以便我可以为我的用例解决这个问题吗?
谢谢!
解决方案
无论您是使用re
还是regex
,您都必须修复您的模式,因为它很容易发生灾难性的回溯。这里不需要原子分组,您需要具有强制性模式的可选分组。此外,您需要修复可能在字符串内的同一位置开始匹配的交替。
您可以使用
(?:[Uu]nit|[Ss]tudio|[Ff]lat)?\s{0,5}\d+[&-]*\w*\s*(?:[Ee]nd|[Gg]reen|[Cc]auseway|[Cc]heapside|[Cc]rescent|[Ss]treet|[Ll]ane|[Ww]alk|[Rr]oad|[Aa]venue|[Dd]rive|[Pp]ark|[Ww]ay|[Pp]lace|[Pp]arade|[Ii]ndustrial[Ee]state|[Tt]rading [Ee]state|[Hh]ouse|[Gg]reen)(?:\s{1,5}\w+){0,5}\s{0,5}[A-Z0-9][A-Z0-9][A-Z0-9]?[A-Z0-9]? {1,2}[0-9][A-Z]{2}
请参阅正则表达式演示。
请参阅Python 演示:
import re
def parse_results(string):
space = r"\s{0,5}"
building_type = r"(?:[Uu]nit|[Ss]tudio|[Ff]lat)?"
street_type = (r"\d+[&-]*\w*\s*"
r"(?:[Ee]nd|[Gg]reen|[Cc]auseway|[Cc]heapside|[Cc]rescent|"
r"[Ss]treet|[Ll]ane|[Ww]alk|[Rr]oad|[Aa]venue|[Dd]rive|"
r"[Pp]ark|[Ww]ay|[Pp]lace|[Pp]arade|[Ii]ndustrial"
r"[Ee]state|[Tt]rading [Ee]state|[Hh]ouse|[Gg]reen)")
postcode = r"[A-Z0-9][A-Z0-9][A-Z0-9]?[A-Z0-9]? {1,2}[0-9][A-Z]{2}"
pattern = re.compile(rf"{building_type}{space}{street_type}(?:\s{{1,5}}\w+){{0,5}}"
rf"{space}{postcode}")
print(pattern.pattern)
try:
return [re.sub(r"\s+", r" ", x) for x in pattern.findall(string)]
except Exception as e:
return (f"Error looking for address, exception {e}")
print(parse_results('Unit 23 End AS4 0SS'))
推荐阅读
- python - 钩子不工作。带有 Pyomo 的 Pyinstaller
- json - 如何使用 boost 属性树生成 json 文件,如示例所示
- asp.net-mvc - 使用 Firebase Admin SDK 向移动设备发送通知
- api - Binance限价卖空API:保证金/订单(卖出)还是保证金/贷款?
- python - 如何修复此列表索引超出范围错误?
- c++ - CMake 和 GitHub Actions - GitHub Actions 上 CMake 库的 Windows 构建未将库链接到测试套件
- google-reporting-api - Google Reports API 返回的项目大小小于 maxResults 参数
- ios - 错误:0909006C:PEM 例程:get_name:没有起始行
- android-recyclerview - 如何在 android 中设置 SimpleExoPlayerView 的最大高度?
- java - 有没有办法读取 Scanner 类 java 中的分隔符?