Creating a 3-D OrderedDict with a Natural Subscriber

I need a dictionary structure that has the following properties:

  • Double attachment (so, 3-dimensional, so many words)
  • Memorizes the order of things added to it for each level.

So, if I add elements to it like this:

# 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' 

The result of the following understanding:

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

Will be:

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

I tried using defaultdict to force the use of this structure for new keys, so I do not need to enter it in a long way, for example:

 # 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 

But defaultdict does not remember the order of the two upper levels. I'm not sure how to merge the behavior, so obviously the top two levels give the defaultdict behavior, because I declared d as such. How can I achieve the structure I want?

+4
source share
2 answers

All you need is a subclass of OrderedDict and add the __missing__ function:

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

The default dict type will call the __missing__ method, if one exists, before raising a KeyError value, which uses the defaultdict type.

See the dict documentation (scroll down to the d[key] description):

New in version 2.5: If the dict subclass defines the __missing__() method, if there is no key key, the d[key] operation calls this method with the key key as an argument. The operation d[key] returns or raises what is returned or raised by calling __missing__(key) if the key is missing. No other operations or methods call __missing__() . If __missing__() not set, a KeyError raised. __missing__() should be a method; it cannot be an instance variable.

Demo:

 >>> 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)] 
+6
source

Old fashioned way:

 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] 
+1
source

Source: https://habr.com/ru/post/1492784/


All Articles