使用自然下标创建三维OrderedDict

时间:2013-07-22 19:49:02

标签: python python-2.7 defaultdict ordereddictionary

我想要一个具有以下属性的字典结构:

  1. 双重嵌套(所以,这么多词中的三维)
  2. 记住每个级别添加的内容的顺序
  3. 所以,如果我像这样添加项目:

    # d = something dict-ish
    d['a']['b']['c'] = 'd'
    d['a'][1][2] = 3
    d['f']['g']['e'] = 'g'
    d['f'][5][6] = 7
    d['a']['foo']['bar'] = 'hello world'
    

    以下理解的结果:

    [(i, j, k, d[i][j][k]) for i in d for j in d[i] for k in d[i][j]]
    

    将是:

    [('a', 'b', 'c', 'd'), ('a', 1, 2, 3), ('a', 'foo', 'bar', 'hello world'), ('f', 'g', 'e', 'g'), ('f', 5, 6, 7)]
    

    我尝试使用defaultdict为新密钥强制执行此结构,因此我不必长途输入,如下所示:

    # long way
    d = OrderedDict()
    d['a'] = OrderedDict([('b', OrderedDict([('c', 'd')]))])
    d['a'][1] = OrderedDict([(2,3)])
    
    # tried to use defaultdict
    d = defaultdict(lambda: defaultdict(lambda: OrderedDict()))
    d['a']['b']['c'] = 'd'
    d['a'][1][2] = 3
    

    defaultdict不记得前两个级别的顺序。我不确定如何合并行为,所以显然前两个级别正在产生defaultdict行为,因为我已声明d是这样的。我怎样才能达到我想要的结构?

2 个答案:

答案 0 :(得分:6)

您只需要继承OrderedDict并添加__missing__函数:

from collections import OrderedDict

class DefaultOrderedDict(OrderedDict):
    def __missing__(self, key):
        self[key] = type(self)()
        return self[key]

默认 dict类型会在提出__missing__之前调用KeyError方法,这是defaultdict类型使用的方法的。

请参阅dict documentation(向下滚动至d[key]说明):

  

2.5版中的新功能:如果dict的子类定义方法__missing__(),如果键不存在,则d[key]操作使用键作为参数调用该方法。如果密钥不存在,d[key]操作将返回或引发__missing__(key)调用返回或引发的任何内容。没有其他操作或方法调用__missing__()。如果未定义__missing__(),则会引发KeyError__missing__()必须是一种方法;它不能是实例变量。

演示:

>>> d = DefaultOrderedDict()
>>> d['a']['b']['c'] = 'd'
>>> d['a'][1][2] = 3
>>> d['f']['g']['e'] = 'g'
>>> d['f'][5][6] = 7
>>> d['a']['foo']['bar'] = 'hello world'
>>> [(i, j, k, d[i][j][k]) for i in d for j in d[i] for k in d[i][j]]
[('a', 'b', 'c', 'd'), ('a', 1, 2, 3), ('a', 'foo', 'bar', 'hello world'), ('f', 'g', 'e', 'g'), ('f', 5, 6, 7)]

答案 1 :(得分:1)

老式的方式:

data = [('a','b','c','d'), ('a',1,2,3), ('f,'g','e','g'), ('f',5,6,7), (a','foo','bar','hello world')]

answer = OrderedDict()
for d in data:
    if d[0] not in answer:
        answer[d[0]] = OrderedDict()
    if d[1] not in answer[d[0]]:
        answer[d[0]][d1] = OrderedDict()
    if d[2] not in answer[d[0]][d1]:
        answer[d[0]][d1][d2] = OrderedDict()
    answer[d[0]][d1][d2] = d[3]