Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 尽可能快的字典式匹配_Python_Algorithm_Optimization_Data Structures_Spell Checking - Fatal编程技术网

Python 尽可能快的字典式匹配

Python 尽可能快的字典式匹配,python,algorithm,optimization,data-structures,spell-checking,Python,Algorithm,Optimization,Data Structures,Spell Checking,我必须在Python中执行类似拼写检查的操作,如下所示: 我有一大堆单词(我们称之为词典)。我现在收到一些文本(我们称之为示例)。我必须搜索词典中的每个示例词。如果我找不到,那么这个示例单词就是一个错误 简而言之,一个强力拼写检查器。然而,在词典中线性搜索每个示例单词肯定会很慢。有什么更好的方法可以做到这一点 复杂的因素是样本和词汇都不是英语的。它使用的语言不是26个字符,而是可以有300多个字符存储在Unicode中 任何算法/数据结构/并行化方法的建议都会有所帮助。以低于100%的准确度为代

我必须在Python中执行类似拼写检查的操作,如下所示:

我有一大堆单词(我们称之为词典)。我现在收到一些文本(我们称之为示例)。我必须搜索词典中的每个示例词。如果我找不到,那么这个示例单词就是一个错误

简而言之,一个强力拼写检查器。然而,在词典中线性搜索每个示例单词肯定会很慢。有什么更好的方法可以做到这一点

复杂的因素是样本和词汇都不是英语的。它使用的语言不是26个字符,而是可以有300多个字符存储在Unicode中


任何算法/数据结构/并行化方法的建议都会有所帮助。以低于100%的准确度为代价的高速算法将是完美的,因为我不需要100%的准确度。我知道Norvig的算法,但它似乎是特定于英语的。

您可以使用一组Unicode字符串:

s = set(u"rabbit", u"lamb", u"calf")
并使用中的
操作符检查单词是否出现:

>>> u"rabbit" in s
True
>>> u"wolf" in s
False
这种查找本质上是O(1),因此字典的大小无关紧要

编辑:以下是(区分大小写)拼写检查器(2.6或更高版本)的完整代码:

(打印<代码>假定您的终端使用UTF-8。)

这就是为什么要使用UTF-8。创建字典中所有单词的集合,然后使用成员资格运算符检查字典中是否存在该单词

下面是一个简化的例子

>>> dictionary = {'Python','check-like', 'will', 'perform','follows:', 'spelling', 'operation'}
>>> for word in "I will have to perform a spelling check-like operation in Python as follows:".split():
    if word in dictionary:
        print "Found {0} in the dictionary".format(word)
    else:
        print "{0} not present in the dictionary".format(word)


I not present in the dictionary
Found will in the dictionary
have not present in the dictionary
to not present in the dictionary
Found perform in the dictionary
a not present in the dictionary
Found spelling in the dictionary
Found check-like in the dictionary
Found operation in the dictionary
in not present in the dictionary
Found Python in the dictionary
as not present in the dictionary
Found follows: in the dictionary
>>> 

python字典中哈希搜索的平均时间复杂度为O(1)。因此,您可以使用“无值字典”(也称为集合)

这就是python字典和集合的用途!) 如果每个单词都有某个值(比如频率),可以将您的词典存储在词典中;如果您只需要检查是否存在,可以将词典存储在一个集合中。搜索它们是O(1),所以会非常快

lex = set(('word1', 'word2', .....))

for w in words:
    if w not in lex:
        print "Error: %s" % w

使用树结构存储单词,这样从根到叶的每个路径都代表一个单词。如果你的遍历不能到达一片叶子,或者在单词末尾之前到达一片叶子,那么你的词典中就没有一个单词了


除了Emil在评论中提到的好处外,还请注意,这可以让你做一些事情,比如回溯,以找到替代拼写。

像每个人都告诉你的那样,尝试一套。设置查找是由经验丰富的程序员在python的C代码中优化的,所以在您的小应用程序中没有办法做得更好


Unicode不是问题:Set和dictionary键可以是Unicode或英文文本,这无关紧要。唯一需要考虑的可能是unicode规范化,因为不同的变音符号顺序在比较时并不相等。如果这是您的语言的问题,我会首先确保词典以规范化的形式存储,然后在检查之前规范化每个单词。例如,
unicodedata.normalize('NFC',word)
首先,您需要创建词典索引。例如,您可以制作自己的索引系统,但更好的方法是使用全文搜索引擎 我可以为您推荐ApacheLucene或sphinx。它既快速又开源。
之后,您可以将搜索查询从python发送到搜索引擎并捕获回复。

这里是我写的一篇关于检查这些内容的帖子。谷歌的建议/拼写检查器也能正常工作


希望有帮助。

@Atriya:不,你在帖子中说你在使用线性搜索。这将使用散列查找。@Atriya:集合仅适用于精确匹配。如果要查找任意长度的前缀或后缀,则需要更复杂的数据结构。@luke14free:O(1)是摊销查找时间,这就是我在上面的答案中使用“基本”一词的原因。平均查找时间不取决于字典的大小。@luke14free,准确地说,平均查找时间不取决于“字典的大小”,而是取决于--表中存储的条目与可用插槽的比率。Python字典的加载系数默认为2/3,这意味着你通常会浪费1/3的内存。还要注意,创建字典不是O(1),因为每次在加载因子上填充字典时,都必须重新对其进行散列(增长)。对于大型字典或可能更高的性能,可以考虑使用MARCIN答案中的TIE。这也被称为TIE或前缀树:检查单词是否在词典中的单词长度的O(n)的顺序,这是不可能超越的。hashmap应该具有相同的复杂性,但通常具有更大的常量因子。因此,对于这个问题,这是一个非常好的数据结构@EmilVikström它还具有更好的内存性能,并可能允许人们获取更多信息(取决于程序正在做什么)。@EmilVikström:在Python上下文中,关于常量的评论是错误的。高度优化的内置set和dict数据结构将很容易比trie的任何Python实现好很多。@SvenMarnach这取决于程序是否将单词视为原子。如果有人想做任何事情,比如计算两个单词之间是否缺少空格,那么使用前缀树的算法将更加有效。它仅用于字典胜出的简单查找。此外,如果词典非常庞大,那么空间性能也会很重要。我在python中使用了手动滚动的三元树,或者在字符串数量增加时进行了实际尝试,效果会更好。我不理解这样的建议,即假设某些东西是最佳的,而不进行分析,或者“一定有原因”进行手工操作。如果您正在优化,请概述您的选项,并分析数据结构和算法复杂性。这是关于专业的。仅仅因为某些东西是经过优化的c代码并不意味着它不能做得更好。最明显的是r
lex = set(('word1', 'word2', .....))

for w in words:
    if w not in lex:
        print "Error: %s" % w