sophiadw
sophiadw

Reputation: 567

reconstruct a python dictionary

I have a python dictionary that has 3 embedded layers, like below (there are many keys in each layer):

my_dict = {key1:{key2:{key3:some_value}}}

Now I want to reconstruct the dictionary by moving key3 as the very first layer. So the dictionary would look like:

my_dict = {key3:{key1:{key2:some_value}}}

I know the silly method of using 3 for loops to reconstruct the whole thing, like

my_new_dict = {}
for key1 in my_dict.keys():
    for key2 in my_dict[key1].keys():
        for key3 in my_dict[key1][key2].keys():
            ### a bunch of code to check if the key already exists and
            ### to move values into the new dictionary from scratch

I wonder if there are better ways to do it. Or maybe dictionary is not the best way to represent such data structure. Then what's a better way of constructing such data? I want to do the reconstruction because I want to do some computation that loops by key3 first, but I cannot get to key3 without looping with key1 and key2 first with my original dictionary.

Upvotes: 0

Views: 297

Answers (2)

Ehsan Kia
Ehsan Kia

Reputation: 1544

Well it doesn't have to be that complicated, especially with defaultdict

from collections import defaultdict
tree = lambda: defaultdict(tree)
new_dict = tree()
for key1 in my_dict:
    for key2 in my_dict[key1]:
        for key3 in my_dict[key1][key2]:
            new_dict[key3][key1][key2] = my_dict[key1][key2][key3]

The only problem is that you're now left with a bunch of defaultdicts, which have bad __repr__'s.

Upvotes: 1

Blckknght
Blckknght

Reputation: 104792

The "bunch of code" doesn't actually need to be very complicated. If you use dict.setdefault to create new intermediate dictionaries as needed, the supposedly complicated part becomes a one-liner. I would also suggest iterating over the items of your dictionaries, rather than indexing them with the keys:

result = {}
for key1, middle_dict in my_dict.items():
    for key2, inner_dict in middle_dict.items():
        for key3, value in inner_dict.items():
            result.setdefault(key3, {}).setdefault(key1, {})[key2] = value

If you're using Python 2, you may want to use iteritems rather than items, as it doesn't allocate a list to hold all the values. In Python 3, items returns an iterable "view" object that doesn't require so much memory.

Upvotes: 0

Related Questions