- 我刚刚解析了一个大文件,我创建了一个包含42.000个字符串/单词的列表。我想查询[反对此列表]以检查给定的单词/字符串是否属于它。所以我的问题是:
进行此类查找的最有效方法是什么?
第一种方法是对列表进行排序(list.sort()
),然后使用
>> if word in list: print 'word'
这真的是微不足道的,我相信有更好的方法来做到这一点。我的目标是应用快速查找,查找给定字符串是否在此列表中。如果您对其他数据结构有任何想法,欢迎使用。然而,我想避免现在更复杂的数据结构,如Tries等。我有兴趣听到关于快速查找或任何其他python库方法的想法(或技巧)可能比简单的in
更快地进行搜索。
我还想知道搜索项的索引
答案 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
中。