免责声明 我是trrex的作者。
对于精确匹配的情况,一种解决方法是使用Trie,正如评论中所提到的那样。trrex是一个库,它可以生成一个Trie-Regex(以正则表达式格式表示的Trie),可以与Python的正则表达式引擎一起使用:
import random
import pandas as pd
import trrex as tx
import re
df = pd.read_csv('jeopardy-small.csv')
with open('words-sample') as infile:
words = [line.strip() for line in infile]
tuples = [(random.randint(1, 250), sentence) for sentence in df['question']]
def fun_kislyuk(ws, ts):
return {t[0] for t in ts if any(w in t[1] for w in ws)}
def fun_trrex(ws, ts):
pattern = re.compile(tx.make(ws, left='', right=''))
return {i for i, s in ts if pattern.search(s)}
if __name__ == "__main__":
print(fun_trrex(words, tuples) == fun_kislyuk(words, tuples))
输出
True
以上功能的时间如下:
11.3 ms ± 34.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
67.5 ms ± 1.75 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
数据是Jeopardy游戏中约2K道问题和500个随机选择的单词列表。您可以在
此处找到重现实验的资源。
更新
如果您使用评论中提到的分组策略,时间改进将增加,以下是该函数:
def fun_grouping_trrex(ws, ts):
pattern = re.compile(tx.make(ws, left='', right=''))
groups = defaultdict(list)
for i, s in ts:
groups[i].append(s)
return {i for i, vs in groups.items() if any(pattern.search(v) for v in vs)}
和时间:
11.2 ms ± 61.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
4.96 ms ± 320 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
67.4 ms ± 1.47 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
使用“分组+trrex”方法,性能可以提高约
10倍。但是要注意,最后的结果非常依赖于数据集。