Skip to content Skip to sidebar Skip to footer

Populating A Nested Dictionary

I have a long list of nested tuples that I am iterating through and appending in a certain way such that an empty dictionary: dict = {} will be filled like this: dict = {a: {b:1,5

Solution 1:

Here is a solution using collections.defaultdict

import random
import collections
choices = ['a', 'b', 'c', 'd', 'e', 'f']

longlist = []
for i in range(1, 101):
    longlist.append((i, tuple(random.sample(choices, 2))))

print longlist

final = collections.defaultdict(lambda: collections.defaultdict(list))

for value, (key1, key2) in longlist:
    final[key1][key2].append(value)


print final

In general, the way that I would change your code would be to first ensure the nested dictionaries exist (collections.defaultdict takes care of this for you) and then always append once.

Something like

for value (key1, key2) in longlist:
    if not your_dict.get(key1):
        your_dict[key1] = {}
    if not your_dict.get(key1).get(key2):
        your_dict[key1][key2] = []
    your_dict[key1][key2].append(value)

Also not the for line vs "for each ..." This is unpacking the items in the iterable. You could also have done

for value, keys in longlist:

but since keys is an iterable as well, you can unpack it as well if you wrap it in parens.

Solution 2:

Without delving much into what you are trying to do, you can rewrite your if statement to not throw an error if the keys do not exist:

if dict_.get(each[1][0], {}).get(each[1][1], None):
    dict_[each[1][0]][each[1][1]].append(each[0])

The dict.get is an extremely useful function in that it returns a certain default value if the given key does not exist.

Also, it seems you expect a list to exist. In the else block, did you mean to do this?

dict_[each[1][0]][each[1][1]] = [each[0]]

This will create a list with a single element, so now dict[...][...].append(...) will work.

I also recommend not using dict to name your variable. It shadows the inbuilt class.

Further improvements might include unpacking items in the head of the for loop, so you don't have to do each[0], each[1], and so on. You could use something like:

for idx, pair in longlist:
    x, y = pair # unpack each pair now
    ...

Full listing:

dict_ = {}
for idx, pair in longlist:
    x, y = pair
    if dict_.get(x, {}).get(y, None):
        dict_[x][y].append(idx)

    else:
        dict_[x] = {y : [idx] }

This is much more readable than before.

Post a Comment for "Populating A Nested Dictionary"