【问题标题】:Most efficient way for a lookup/search in a huge list (python)在巨大列表中查找/搜索的最有效方法(python)
【发布时间】:2026-02-13 07:30:01
【问题描述】:

-- 我刚刚解析了一个大文件,并创建了一个包含 42.000 个字符串/单词的列表。我想查询 [针对此列表] 以检查给定的单词/字符串是否属于它。所以我的问题是:

这种查找最有效的方法是什么?

第一种方法是对列表进行排序 (list.sort()),然后使用

>> if word in list: print 'word'

这真的是微不足道的,我相信有更好的方法来做到这一点。我的目标是应用快速查找来查找给定字符串是否在此列表中。如果您对其他数据结构有任何想法,欢迎提出。然而,我现在想避免使用更复杂的数据结构,如 Tries 等。我有兴趣听到关于快速查找或任何其他 python 库方法的想法(或技巧),这些方法可能比简单的in 更快地进行搜索。

我也想知道搜索项的索引

【问题讨论】:

  • 如果您预计稍后会进行复杂的查找 - 复杂我的意思不是微不足道的 - 我建议您将其存储在 sqlite3

标签: python search list performance


【解决方案1】:

不要创建list,而是创建set。它在恒定时间内进行查找。

如果您不想要集合的内存开销,请保留一个排序列表并使用 bisect 模块搜索它。

from bisect import bisect_left
def bi_contains(lst, item):
    """ efficient `item in lst` for sorted lists """
    # if item is larger than the last its not in the list, but the bisect would 
    # find `len(lst)` as the index to insert, so check that first. Else, if the 
    # item is in the list then it has to be at index bisect_left(lst, item)
    return (item <= lst[-1]) and (lst[bisect_left(lst, item)] == item)

【讨论】:

  • 非常感谢 THC4k 的详细回复。实际上,我正在考虑自己应用二进制搜索,但正如我所见,这就是 bisect 模块所做的事情,所以你节省了我的时间:)。再次感谢您的帮助。
  • @user229269,您锁定了帖子的错误部分!你可能想要set,而不是list
  • @Mike Graham 我知道你在说什么,但我担心如果我使用集合我可能会遇到记忆问题,因为我的列表实际上是一个快速增长的单词列表,即将结束多达 100.000 个字符串甚至更多
  • @user229269, 100000 个项目并不多。对这么多项目使用set 而不是list 只会增加set 的数据确实增长到如此之大会导致内存问题,那么您可能需要考虑使用一种非常不同的技术,例如将数据存储在数据库中。
  • 是的,实际上你 (@Mike Graham) 是对的 :) -- 我已经用过套装了。非常感谢让我重新考虑它
【解决方案2】:

关于未考虑的集合与列表的一点:在“解析大文件”中,人们期望需要处理重复字/字符串。你根本没有提到这一点。

显然,将新单词添加到集合中会即时删除重复单词,而不会增加 CPU 时间或您的思考时间。如果你用一个列表来尝试它,它会以 O(N**2) 结束。如果您将所有内容附加到列表并在最后删除重复项,那么最聪明的方法是......鼓声......使用一组,并且列表的(小)内存优势可能会被重复。

【讨论】:

    【解决方案3】:

    使用这个程序,看起来 dicts 是禁食,第二个,bi_contains 第三个列表:

    from datetime import datetime
    
    def ReadWordList():
        """ Loop through each line in english.txt and add it to the list in uppercase.
    
        Returns:
        Returns array with all the words in english.txt.
    
        """
        l_words = []
        with open(r'c:\english.txt', 'r') as f_in:
            for line in f_in:
                line = line.strip().upper()
                l_words.append(line)
    
        return l_words
    
    # Loop through each line in english.txt and add it to the l_words list in uppercase.
    l_words = ReadWordList()
    l_words = {key: None for key in l_words}
    #l_words = set(l_words)
    #l_words = tuple(l_words)
    
    t1 = datetime.now()
    
    for i in range(10000):
        #w = 'ZEBRA' in l_words
        w = bi_contains(l_words, 'ZEBRA')
    
    t2 = datetime.now()
    print('After: ' + str(t2 - t1))
    
    # list = 41.025293 seconds
    # dict = 0.001488 seconds
    # set = 0.001499 seconds
    # tuple = 38.975805 seconds
    # list with bi_contains = 0.014000 seconds
    

    【讨论】:

    • 对 dicts 更快感到惊讶。下一个问题是生成“l_words”对象需要多长时间。 +1!