在巨大的列表中查找/搜索的最有效方法(python)

时间:2010-04-23 18:47:53

标签: python search list performance

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

进行此类查找的最有效方法是什么?

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

>> if word in list: print 'word'

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

我还想知道搜索项的索引

4 个答案:

答案 0 :(得分:50)

不要创建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)

答案 1 :(得分:4)

使用这个程序看起来像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

答案 2 :(得分:3)

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

显然,在一个集合中添加新单词可以动态删除重复项,而无需额外的CPU时间或思考时间。如果你尝试使用列表,它会结束O(N ** 2)。如果您将所有内容追加到列表中并在最后删除重复项,那么最明智的方法就是...滚动...使用一个集合,列表的(小)内存优势很可能会被重复。

答案 3 :(得分:-1)

如果您预计稍后会进行复杂的查找 - 而且复杂意味着并非琐碎 - 我建议您将其存储在sqlite3中。