问题:大型静态字符串列表提供为A
,长字符串提供为B
,A
中的字符串都非常短(关键字列表),我想检查A
中的每个字符串是否都是B
的子字符串并获取它们。
现在我使用一个简单的循环:
result = []
for word in A:
if word in B:
result.append(word)
但是当A包含~500,000或更多项目时,它会发生疯狂。
是否有适合此问题的库或算法?我尽力搜索但没有运气。
谢谢!
答案 0 :(得分:14)
你的问题足够大,你可能需要用算法蝙蝠击中它。
查看Aho-Corasick算法。您的问题陈述是对该算法所解决的问题的解释。
另外,请查看Nicholas Lehuen的PyTST包的作品。
在相关的Stack Overflow消息中也有引用提及其他算法,如Rabin-Karp:Algorithm for linear pattern matching?
答案 1 :(得分:2)
根据长字符串的长度,可能值得这样做:
ls = 'my long string of stuff'
#Generate all possible substrings of ls, keeping only uniques
x = set([ls[p:y] for p in range(0, len(ls)+1) for y in range(p+1, len(ls)+1)])
result = []
for word in A:
if word in x:
result.append(word)
显然,如果你的长字符串非常非常长,那么这也会变得太慢,但对于几百个字符以下的任何字符串它应该更快。
答案 2 :(得分:1)
我不知道这是否会更快,但它更加pythonic:
result = [x for x in A if x in B]
答案 3 :(得分:1)
将B
的所有单词单词打包到一个新列表中,该列表由' '
分割的原始字符串组成。然后,对于B
中的每个元素,针对A
的每个元素测试成员资格。如果您找到一个(或多个),请从A
删除它们,并在A
为空时立即退出。
如果没有选择退出设置,您的方法似乎会让500,000名候选人参与其中。
答案 4 :(得分:1)
假设您拥有相同长度的所有关键字(稍后您可以将此算法扩展为不同的长度)
我接下来可以建议:
预先计算每个关键字的一些哈希值(例如xor哈希):
hash256 = reduce(int.__xor__, map(ord, keyword))
创建一个字典,其中key是一个哈希值,以及相应关键字的值列表
保存关键字长度
curr_keyword = []
for x in B:
if len(curr_keyword) == keyword_length:
hash256 = reduce(int.__xor__, map(ord, curr_keyword))
if hash256 in dictionary_of_hashed:
#search in list
curr_keyword.append(x)
curr_keyword = curr_keyword[1:]
像这样的东西