Python - 快速文件搜索

时间:2012-02-28 08:20:49

标签: python search indexing python-3.x

我有一个大(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有点输入错误也应找到行。

2 个答案:

答案 0 :(得分:4)

  1. 此行无效:

    10 ** (len(t) / len(word))

  2. 你需要更好的变量名,截至目前尚不清楚“s”和“t”是什么。单字母变量名称仅在数学和循环变量中可接受。你正在寻找什么,或者你正在寻找什么?现在使用的功能对我来说没有多大意义。

  3. 由于你只匹配你搜索的任何东西的第一场比赛,在某些情况下分割是没有意义的,所以你可能最后移动分割,但这取决于你实际搜索的内容,这是不清楚的(见2)。

  4. 更新:要真正获得最佳性能,您需要进行配置,测试,配置和测试。但我建议这是第一次开始:

    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)

该函数将搜索持久字典中的字符串,并根据您的逻辑为您提供计算。它会比每次迭代更快。