【发布时间】:2016-11-22 11:44:50
【问题描述】:
我的 Python 脚本中有一个 word:count 对字典。从这本字典中,我想提取匹配字符串列表中任何项目的条目。
我找到了一个使用正则表达式的有效解决方案(见下文),但它需要永远(运行约 10 小时)。我觉得必须有更快的方法来做到这一点 - 你们对如何改进我的代码有任何意见/想法吗?
import re
dicti={'the':20, 'a':10, 'over':2}
regex_list=['the', 'an?']
extractddicti= {k:v for k,v in dicti.items() if any (re.match("^"+regex+"$",k) for regex in regex_list)}
实际上,字典有大约 60,000 个条目,regex_list 约为 1,000。正则表达式列表中的项目是正则表达式字符串,即包含特殊字符如 ?,括号如 (a|b|c) 等。它们可能匹配多个条目字典。
更新/编辑
(查看已接受的答案以更好地实现相同的想法)
按照 Keozon 和其他人的建议,我首先像这样编译了我的正则表达式:
regex_list=['the', 'an?']
regex_list_compiled=[re.compile("^"+i+"$") for i in regex_list]
然后稍微调整了我的搜索功能:
extractddicti= {k:v for k,v in dicti.items() if any (re.match(regex,k) for regex in regex_list_compiled)}
性能差异非常惊人:使用包含 14800 个项目的字典和包含 1,100 个正则表达式的列表进行的测试运行需要 34 分钟(不编译),而编译则只用了不到一 (!) 分钟。没想到会如此戏剧化。感谢您的所有帮助!
【问题讨论】:
-
在您的完整版中,您是否正在编译列表中的正则表达式?如果没有,请这样做。这就是存在编译选项的确切原因。事实上,每个正则表达式在每次与字符串进行比较时都会被编译。 docs.python.org/2/library/re.html#re.compile
-
使用
dicti.iteritems()会提供一个小的改进(除非这是python3)。但更重要的是,确保您的正则表达式不会受到 catastrophic backtracking 的影响。 -
我将继续假设您的 real 正则表达式更复杂。因为使用正则表达式搜索“the”可能不是最快的方法。 IE。如果您正在搜索简单的字符串,请使用 str.find
-
另外,请确保您在正则表达式定义中使用原始字符串文字,否则您可能会遇到令人惊讶的行为(
r'the'而不是'the') -
re.match表示字符串的开头,因此^是不必要的(除非它是多行的)。如果你使用 Python 3,你可以考虑re.fullmatch。
标签: python regex list dictionary list-comprehension