如何在Python中创建字典的字典

如何在Python中创建字典的字典,python,dictionary,Python,Dictionary,因此,我正在学习一门自然语言处理课程,我需要创建一个三角图语言模型,根据一些样本数据生成在一定程度上看起来“真实”的随机文本 基本上需要创建一个“三角形”来容纳各种3个字母的语法单词组合。我的教授暗示,这可以通过拥有一本字典中的字典来实现,我试图使用以下方法创建一本字典中的字典: trigram = defaultdict( defaultdict(defaultdict(int))) 但是,我得到一个错误,它说: trigram = defaultdict( dict(dict(int)))

因此,我正在学习一门自然语言处理课程,我需要创建一个三角图语言模型,根据一些样本数据生成在一定程度上看起来“真实”的随机文本

基本上需要创建一个“三角形”来容纳各种3个字母的语法单词组合。我的教授暗示,这可以通过拥有一本字典中的字典来实现,我试图使用以下方法创建一本字典中的字典:

trigram = defaultdict( defaultdict(defaultdict(int)))
但是,我得到一个错误,它说:

trigram = defaultdict( dict(dict(int)))
TypeError: 'type' object is not iterable
如何创建一个3层嵌套字典或一个
int
值字典的字典字典

我猜如果人们不知道如何回答堆栈溢出的问题,他们会投反对票。我将添加一些背景知识,以便更好地为那些愿意提供帮助的人解释这个问题

这个三元图用于跟踪三重单词模式。在文本语言处理软件和几乎所有自然语言处理软件中都使用了“现在想想siri或google”

如果我们将字典的3个级别指定为dict1 dict2和dict3,那么解析文本文件并阅读语句“男孩跑”将具有以下功能:

具有“the”键的dict1。访问该键将返回包含键“boy”的dict2。访问该键将返回最终dict3,其中包含键“runs”,现在访问该键将返回值1

这象征着在本文中“男孩跑”出现了一次。如果我们再次遇到它,那么我们将遵循相同的过程,增加1到2。如果我们遇到“女孩行走”,那么dict2“the”keys字典现在将包含“girl”的另一个键,该键的dict3键为“walks”,值为1,依此类推。最终,在解析大量文本(并跟踪字数)后,您将得到一个三叉图,该三叉图可以根据某个起始词在先前解析的文本中出现的次数来确定其与3个单词组合的相似性

这可以帮助您创建语法规则来识别语言,或者在我的例子中,创建随机生成的文本,看起来非常像语法英语。我需要一个三层词典,因为在三个单词组合的任何位置,都可能有另一个单词可以创建一组完全不同的组合。我尽了最大的努力来解释trig公羊和它们背后的目的,尽我所能…承认我刚刚声明了几周前的类

现在…说到这里,我该如何创建一个字典字典,它的基本字典在python中保存int类型的值

trigram=defaultdict(defaultdict(defaultdict(int)))


为我抛出一个错误

我以前尝试过嵌套的
defaultdict
,解决方案似乎是
lambda
调用:

trigram = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))

trigram['a']['b']['c'] += 1

这并不漂亮,但我怀疑嵌套字典的建议是为了高效查找。

一般来说,要创建一个嵌套的三角形字典,已经发布的解决方案可能会起作用。如果您想扩展一个更通用的解决方案,您可以执行以下操作之一,其中一个是从中采用的,另一个是使用

解决方案1:

class ngram(dict):
    """Based on perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return super(ngram, self).__getitem__(item)
        except KeyError:
            value = self[item] = type(self)()
            return value
from collections import defaultdict
class ngram(defaultdict):
    def __init__(self):
        super(ngram, self).__init__(ngram)
解决方案2:

class ngram(dict):
    """Based on perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return super(ngram, self).__getitem__(item)
        except KeyError:
            value = self[item] = type(self)()
            return value
from collections import defaultdict
class ngram(defaultdict):
    def __init__(self):
        super(ngram, self).__init__(ngram)
使用解决方案1进行演示

>>> trigram = ngram()
>>> trigram['two']['three']['four'] = 4
>>> trigram
{'two': {'three': {'four': 4}}}
>>> a['two']
{'three': {'four': 4}}
>>> a['two']['three']
{'four': 4}
>>> a['two']['three']['four']
4
使用解决方案2进行演示

>>> a = ngram()
>>> a['two']['three']['four'] = 4
>>> a
defaultdict(<class '__main__.ngram'>, {'two': defaultdict(<class '__main__.ngram'>, {'three': defaultdict(<class '__main__.ngram'>, {'four': 4})})})
>a=ngram()
>>>a['2']['3']['4']=4
>>>a
defaultdict(,{'two':defaultdict(,{'two':defaultdict(,{'four':4})})

如果只是提取和检索三叉树,您应该使用
NLTK
来尝试:

>>> import nltk
>>> sent = "this is a foo bar crazycoder"
>>> trigrams = nltk.ngrams(sent.split(), 3)
[('this', 'is', 'a'), ('is', 'a', 'foo'), ('a', 'foo', 'bar'), ('foo', 'bar', 'crazycoder')]
# token "a" in first element of trigram
>>> first_a = [i for i in trigrams if i[0] == "a"]
[('a', 'foo', 'bar')]
# token "a" in 2nd element of trigram
>>> second_a = [i for i in trigrams if i[1] == "a"]
[('is', 'a', 'foo')]
# token "a" in third element of trigram
>>> third = [i for i in trigrams if i[2] == "a"]
[('this', 'is', 'a')]
# look for 2gram in trigrams
>> two_foobar = [i for i in trigrams if "foo" in i and "bar" in i]
[('a', 'foo', 'bar'), ('foo', 'bar', 'crazycoder')]
# look for a perfect 3gram
>> perfect = [i fof i in trigrams if "foo bar crazycoder".split() == i]
[('foo', 'bar', 'crazycoder')]

defaultdict\uuuu init\uuuu
方法接受一个可调用的参数。传递给
defaultdict
的可调用对象必须是无参数的可调用对象,并且必须返回默认值的实例

嵌套
defaultdict
的问题在于
defaultdict
\uuuu init\uuuuuu
需要一个参数。给定
defaultdict
该参数意味着包装
defaultdict
\uuu init\uuuuuu
参数不是可调用的,而是有一个
defaultdict实例de>,它是不可调用的


@pcoving的
lambda
解决方案会起作用,因为它创建了一个匿名函数,返回一个
defaultdict
,该函数使用一个函数初始化,该函数返回字典嵌套中每一层的正确类型
defaultdict

你确实是一个疯狂的编码者。@AlexA。就像我说的那样,它是类教授是谁建议我们这么做的。我想这是因为我们正在使用它来构建一个语言模型,每个字典级别的键数量未知。是的,我只是对字典的字典部分很感兴趣。就您的用例而言,据我所知,在Python世界中,这似乎是一种相当明智的方法。D当然,不要对反对票太灰心,因为如果你问我的话,你的问题似乎是一个公平的问题。从这个意义上说,解决方案更可扩展到>3克,但对于大数据,你可能需要智能的搜索方式,而不是列表理解。