Question

I have dictionary with three-level nesting, eg:

d = {
    'sp1':{
        'a1':{'c1':2,'c2':3},
        'a2':{'c3':1,'c4':4}
        },
    'sp2':{
        'a1':{'c1':3,'c2':3},
        'a2':{'c3':2,'c4':0}
        }
    }

All 2nd-level dictionaries contain the same elements, so I want to change it to

d2 = {'a1':{'c1':{'sp1':2,'sp2':3}, 'c2':{'sp1':3,'sp2':3}}}

i.e. essentially switch nesting order. But when I write code like

d2 = {}
d2['a1']['c1']['sp1'] = 2

It just throws KeyError with whatever values happens to be 'a1'. How do I perform such operation?

Was it helpful?

Solution 2

To do this, you can use defaultdict, which allows you to define a default initialization action on a dict.

In your case, you want a reverse-order recursive defaultdict, with a classmethod reverse_recursive_make() which unrolls and reverses the key order:

  • when passed in a key-value pair or None, returns a (toplevel) dict
  • when passed in a dict, recurses into each of the {k:v} pairs

I'm not going to write the code for that because what you want can be much more easily achieved with SQL, like I commented.

FOOTNOTE: your version with lambdas (comment below) is perfect.

(If you insist on using dicts, and not some other data structure)

OTHER TIPS

If you are doing it manually like the snippet you tried, this is how you should be doing it:

>>> d = {
...     'sp1':{
...         'a1':{'c1':2,'c2':3},
...         'a2':{'c3':1,'c4':4}
...         },
...     'sp2':{
...         'a1':{'c1':3,'c2':3},
...         'a2':{'c3':2,'c4':0}
...         }
...     }
>>>
>>> e = {}
>>> e['a1'] = {}
>>> e['a1']['c1'] = {}
>>> e['a1']['c1']['sp1'] = d['sp1']['a1']['c1']
>>> e['a1']['c2'] = {}
>>> e['a1']['c2']['sp1'] = d['sp1']['a1']['c2']
>>> e['a2'] = {}
>>> e['a2']['c1'] = {}
>>> e['a2']['c2'] = {}
>>> e['a1']['c1']['sp2'] = d['sp2']['a1']['c1']
>>> e['a1']['c2']['sp2'] = d['sp2']['a1']['c2']
>>> e
{'a1': {'c2': {'sp1': 3, 'sp2': 3}, 'c1': {'sp1': 2, 'sp2': 3}}}
>>>

But it is unclear as to why you are doing it. As OmnipotentEntity suggested in the comments, may be you need to use a different data structure to store the data.

something like this should work

d_final = {}
for k in d.keys():
    d2 = d[k]
    for k2 in d2.keys():
        d3 = d2[k2]
        for k3 in d3.keys():
            d4 = d_final.get(k2,{})
            d4[k] = d3[k3]
            d_final[k2] = d4

I may have my indexing off a little, but that should be about right.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top