我有一个大(0.5-150万)行数的文件,每行都是一个文件名(长度约为50-100个字符)。我需要的是通过给定查询快速搜索这些行。现在我的代码看起来像这样:
def similarity(haystack, needle):
words = re.findall(r'\w+', haystack.lower()) # replacing by split with separators reduces time by about 4 seconds
for word in words:
if word == needle:
return 10
for word in words:
if word.startswith(needle):
return 10 ** (len(needle) / len(word))
if needle in haystack:
return 1
return 0
def search(text):
text = text.lower()
lines = [(similarity(x, text), x) for x in lines]
return [x[1] for x in sorted(lines, reverse = True)[:15]]
它在我的PC上的示例文件上运行大约15秒(几乎所有时间都在similarity()
函数中),我希望它几秒钟内立即运行。怎么办呢?
我认为索引可能有所帮助,但不了解其可能的结构。并且,如果可能的话,我希望搜索“更模糊” - 例如用N-gram或类似的东西。但现在主要担心的是速度。
UPD:
多次搜索相同的lines
。
needle
总是一个字。
“更模糊”意味着即使needle
有点输入错误也应找到行。
答案 0 :(得分:4)
此行无效:
10 ** (len(t) / len(word))
你需要更好的变量名,截至目前尚不清楚“s”和“t”是什么。单字母变量名称仅在数学和循环变量中可接受。你正在寻找什么,或者你正在寻找什么?现在使用的功能对我来说没有多大意义。
由于你只匹配你搜索的任何东西的第一场比赛,在某些情况下分割是没有意义的,所以你可能最后移动分割,但这取决于你实际搜索的内容,这是不清楚的(见2)。
更新:要真正获得最佳性能,您需要进行配置,测试,配置和测试。但我建议这是第一次开始:
def similarity(haystack, needle):
if needle not in haystack:
return 0
words = haystack.lower().split()
if needle in words:
return 10
for word in words:
if word.startswith(needle):
return 10 ** (len(needle) / len(word))
return 1
答案 1 :(得分:0)
由于您使用相同的文件来搜索字符串。如果您使用持久字典,则可以加快搜索速度。
考虑你的逻辑。你可以用它。
import shelve
import os
PERSISTENT_DICT_FILENAME = "my_persistent_dict"
def create_a_persitant_dict(haystack_filename):
pd = shelve.open(PERSISTENT_DICT_FILENAME)
f = open(haystack_filename)
for filename in f:
filename_len = len(filename)
filename = filename.lower()
for i in range(1,filename_len):
partial_filename = filename[:i]
calculation = 10 ** ((len(partial_filename)*1.0)/filename_len)
if pd.has_key(partial_filename):
if calculation > pd[partial_filename]:
pd[partial_filename] = calculation
else:
pd[partial_filename] = calculation
pd.close()
def search_string(needle):
needle = needle.lower()
pd = shelve.open(PERSISTENT_DICT_FILENAME)
if pd.has_key(needle):
return_val = pd[needle]
else:
return_val = 0
pd.close()
return return_val
if __name__ == "__main__":
#create_a_persitant_dict("a_large_file.txt")
needle = raw_input("Enter the string to search")
print search_string(needle)
说明:
create_a_persitant_dict(haystack_filename)
将创建一个读取大文件的持久字典。键是一个在文件中找到的字符串(例如:如果文件中的一行是“World.txt”,键将是“w”,“wo”,“wor”,“worl”......等等,值是每个键的计算(10 **等)。
这只是一次性昂贵的操作。但想法是加快搜索速度。
search_string(needle)
该函数将搜索持久字典中的字符串,并根据您的逻辑为您提供计算。它会比每次迭代更快。