问题描述
我有一个10万个单词的列表。我希望非常有效地搜索这个已知单词列表中是否存在我阅读的单词。使用Python实施时,可以在Trie或Set中更快地搜索这两种数据结构中的哪一种?
解决方法
如果只是“输入或不输入”,不检查前缀或后缀,则只需使用set
。它们是内置的,这本身使它们更加方便,并且比您将在Python中手动实现的任何东西都快。尝试有其位置,但是对于简单的成员资格测试,set
在几乎所有情况下都很好。不要过早地进行优化;如果使用set
可以足够快地运行,则甚至没有理由考虑其他选择。
如果只需要检查单词是否已存在,则集合(哈希表)总是更好。 (摊销的)时间复杂度是恒定的。
特里对于其他用例很有意义,例如查找以某些前缀开头的已经存在的单词。
要总结其他朋友的评论,绝对推荐使用set
。
编写此基准比较python set
和marisa-trie
,即:
适用于Python的静态内存高效Trie式结构
结果几乎是set
的10个数量级:
function [trie_performance_test] finished in 22 ms
function [set_performance_test] finished in 2 ms
代码:
# pip install marisa-trie
import functools
from timeit import default_timer as timer
import marisa_trie
import requests
word_site = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain"
response = requests.get(word_site)
WORDS = [w.decode('utf8') for w in response.content.splitlines()]
def timeit(func):
@functools.wraps(func)
def newfunc(*args,**kwargs):
startTime = timer()
func(*args,**kwargs)
elapsedTime = timer() - startTime
print('function [{}] finished in {} ms'.format(
func.__name__,int(elapsedTime * 1000)))
return newfunc
@timeit
def trie_performance_test(words=WORDS):
trie = marisa_trie.Trie(words)
for key in words:
key_id = trie.get(key)
@timeit
def set_performance_test(words=WORDS):
words_set = set(words)
for key in words:
if key in words_set:
pass
trie_performance_test()
set_performance_test()