在Python中尝试或设置

问题描述

我有一个10万个单词的列表。我希望非常有效地搜索这个已知单词列表中是否存在我阅读的单词。使用Python实施时,可以在Trie或Set中更快地搜索这两种数据结构中的哪一种?

解决方法

如果只是“输入或不输入”,不检查前缀或后缀,则只需使用set。它们是内置的,这本身使它们更加方便,并且比您将在Python中手动实现的任何东西都快。尝试有其位置,但是对于简单的成员资格测试,set在几乎所有情况下都很好。不要过早地进行优化;如果使用set可以足够快地运行,则甚至没有理由考虑其他选择。

,

如果只需要检查单词是否已存在,则集合(哈希表)总是更好。 (摊销的)时间复杂度是恒定的。
特里对于其他用例很有意义,例如查找以某些前缀开头的已经存在的单词。

,

要总结其他朋友的评论,绝对推荐使用set

编写此基准比较python setmarisa-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()