使用trie的Python拼写检查器

使用trie的Python拼写检查器,python,trie,Python,Trie,我正在尝试使用trie数据结构实现拼写检查器。我目前对节点有以下概述: class Node: def __init__(self): self.next = {} self.word_marker = False def add_item(self, string): #if the length of the string is 0 then return. When the end of the word

我正在尝试使用trie数据结构实现拼写检查器。我目前对
节点有以下概述:

class Node:
    def __init__(self):
        self.next = {}
        self.word_marker = False

    def add_item(self, string):
        #if the length of the string is 0 then return. When the end of the word 
        #comes set the word_marker to true
        if len(string) == 0:
            self.word_marker = True
            return
        #set the key to the first letter of the string and reformat the string to reflect the first letter taken out
        #ultimately going to store the letters for each node as the key
        key = string[0]
        string = string[1:]

        #if there is a key in the dictionary, then recursively call add_item with new string
        if key in self.next:
            self.next[key].add_item(string)

        else:
            node = Node()
            self.next[key] = node
            node.add_item(string)

我要做的下一件事是编写函数来搜索
字符串
,然后返回建议的拼写。(
def correct(self,string)
)。我将如何通过这个trie来实现搜索?假设我已经通过定义根节点
root
,然后对列表中的每个单词使用
add\u item
,向trie添加了一个单词列表。

如果您还没有,您可能想查看Norvig的“”

这里有一个与您的问题相关的答案:

也考虑使用诸如 或


虽然不是一个直接的答案,但您可能希望从以下更先进的Trie实现开始:

class Trie:

    def __init__(self):
        self.__final = False
        self.__nodes = {}

    def __repr__(self):
        return 'Trie<len={}, final={}>'.format(len(self), self.__final)

    def __getstate__(self):
        return self.__final, self.__nodes

    def __setstate__(self, state):
        self.__final, self.__nodes = state

    def __len__(self):
        return len(self.__nodes)

    def __bool__(self):
        return self.__final

    def __contains__(self, array):
        try:
            return self[array]
        except KeyError:
            return False

    def __iter__(self):
        yield self
        for node in self.__nodes.values():
            yield from node

    def __getitem__(self, array):
        return self.__get(array, False)

    def create(self, array):
        self.__get(array, True).__final = True

    def read(self):
        yield from self.__read([])

    def update(self, array):
        self[array].__final = True

    def delete(self, array):
        self[array].__final = False

    def prune(self):
        for key, value in tuple(self.__nodes.items()):
            if not value.prune():
                del self.__nodes[key]
        if not len(self):
            self.delete([])
        return self

    def __get(self, array, create):
        if array:
            head, *tail = array
            if create and head not in self.__nodes:
                self.__nodes[head] = Trie()
            return self.__nodes[head].__get(tail, create)
        return self

    def __read(self, name):
        if self.__final:
            yield name
        for key, value in self.__nodes.items():
            yield from value.__read(name + [key])
class-Trie:
定义初始化(自):
self.\uuu final=False
self._节点={}
定义报告(自我):
返回“Trie”。格式(len(self),self.\uu final)
定义获取状态(自身):
返回self.\u final,self.\u节点
定义设置状态(自身、状态):
self.\u final,self.\u节点=状态
定义(自我):
返回len(self.\u节点)
定义(自我):
返回自我。\u最终
def___;包含____;(自身,数组):
尝试:
返回自我[数组]
除KeyError外:
返回错误
定义(自我):
屈服于自己
对于self中的节点。\uuuu nodes.values():
节点屈服
def uu getitem uu(自身,数组):
返回self.\u获取(数组,False)
def创建(自身、阵列):
self.\uuu get(数组,True)。\uuuu final=True
def读取(自):
自读产量([])
def更新(自身、阵列):
self[array]。\uuuu final=True
def delete(自我,阵列):
self[array]。\uuuu final=False
def prune(自我):
对于键,元组中的值(self.\u nodes.items()):
如果不是value.prune():
del self.\u节点[键]
如果不是len(自我):
self.delete([])
回归自我
定义获取(自、数组、创建):
如果阵列:
头,*尾=数组
如果创建和头不在self.\u节点中:
self.\uu节点[head]=Trie()
返回self.\u节点[head]。\u获取(tail,create)
回归自我
定义读取(自我,名称):
如果是自成定局:
屈服名称
对于键,在self.\u nodes.items()中输入值:
从值中产生。读取(名称+键)

是的,我看到了,但我不想依赖概率。我希望能够解决过滤aaaappppllleee=>苹果和果冻=>果冻的能力。第一个是区分重复字母,第二个是替换元音。请阅读有关编辑距离的部分。听起来这就是你要找的。其次,不要被概率论吓跑。诺维格知道自己在做什么,而且用它是有原因的。如果你想要一个好的通用拼写校正器,那就是最好的选择。手工编织的启发法只能让你走到这一步。我看到了这一点,但是我想尝试通过每个案例来看看我们是否可以通过编程来做一些事情。为什么
jella
映射到
jello
?元音有什么特别之处?字母
a
在qwerty键盘上紧靠着
s
,所以肯定
jells
是一个更合适的人选。我认为有很多情况需要涵盖,但我只想一次了解一个。元音,然后是辅音,然后是键盘距离。显然,这可能会很快变得复杂,所以我想先做一些简单的;在d中使用
k
cool Thank将进行更改