Python-快速文件搜索

Python-快速文件搜索,python,search,indexing,python-3.x,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 w

我有一个文件,有大量(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:

对相同的
进行多次搜索

needle
始终是一个单词

“更模糊”意味着即使
pinder
有点输入错误,它也应该找到行

  • 此行不起任何作用:

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

  • 您需要更好的变量名,目前还不清楚“s”和“t”是什么。单字母变量名仅在数学和循环变量中可用。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
    

    因为您使用的是同一个文件来搜索字符串。如果使用持久字典,可以加快搜索速度

    考虑到你的逻辑。你可以用这个

    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)
    

    该函数将在持久性字典中搜索字符串,并根据您的逻辑进行计算。它将比每次迭代都要快。

    1.当然,在这之前有
    返回值
    。2.好的,将名称更改为更有意义的名称。3.一行不太可能包含一次以上出现的
    指针
    。这是错误的这是一个明显的优化,但它确实有帮助=)谢谢,现在它在2-3秒内执行。顺便说一句,这不是一个使搜索“更模糊”的简单方法吗?@Chersaya:简单,不。比这更模糊需要查找搜索字符串等的部分。这最好通过词干词典等来完成,然后进入全文搜索引擎模式。事实上,有一个简单的方法可以做到这一点:使用全文搜索引擎然而,写一个并不简单。你会建议使用什么引擎呢?据我所知,它们中的大多数用于搜索包含某种模式的文件,而不是搜索单个文件中的一行。我建议不要重新发明轮子,使用专用的全文搜索引擎,如。我尝试过建立反向索引,不是为每个子字符串,而是仅为单独的单词。大约需要80MB(未压缩)。我担心你建议的索引的大小。。。