Home > front end >  Creating nested dictionary from two lists one of which contains dictionaries
Creating nested dictionary from two lists one of which contains dictionaries

Time:05-27

Very similar to this question but with an added caveat.

I have two lists identical in length. One contains my keys, and the other contains a list of dictionaries belonging to said keys. Example below (yes the Nones are intentional)

keys = ['key1', 'key2, 'key3']
vals = [[{'subkey1': 'val1', 'subkey2': 'val2'}], [{'subkey1: 'val2'},None],[{'subkey1':'val3'}, {'subkey3':'val1}, None, None]]

What I'd like to do is match each dictionary in each list to a key to create a nested dict.

So something like below:

final = {'key1':{'subkey1': 'val1', 'subkey2': 'val2'}, 'key2':{'subkey1': 'val2'}, 'key3':{'subkey1':'val3'}, {'subkey3':'val1'}}

I know we can use dictionary comprehension to do this. I created a dictionary of empty dicts.

s = {}
for i in keys:
    for v in vals:
        s[i] = {}
        break  

Then I wrote the following to iterate through the list of dicts I'd like to pair up accounting for the non dictionary values in my list.

x = 0
while x < len(keys):
    for i in keys:
        for element in vals[x]:
            if isinstance(element, dict) == True:
                s[str(i)].append(element)
            else:
                print('no')
    x=x 1

However when I run this, I get AttributeError: 'NoneType' object has no attribute 'append'

How can I append to a dictionary using this for loop?

CodePudding user response:

For the less readable dictionary comprehension solution

keys = ['key1', 'key2', 'key3']
vals = [
  [{'subkey1': 'val1', 'subkey2': 'val2'}],
  [{'subkey1': 'val2'}, None],
  [{'subkey1': 'val3'}, {'subkey3':'val1'}, None, None]
]

s = {
    k: {
        sk: sv for d in (x for x in v if x is not None) for sk, sv in d.items()
    } for k, v in zip(keys, vals)
}

Gives

{'key1': {'subkey1': 'val1', 'subkey2': 'val2'},
 'key2': {'subkey1': 'val2'},
 'key3': {'subkey1': 'val3', 'subkey3': 'val1'}}

CodePudding user response:

This can be done fairly easily using a defaultdict:

from collections import defaultdict

keys = ['key1', 'key2', 'key3']
vals = [
  [{'subkey1': 'val1', 'subkey2': 'val2'}],
  [{'subkey1': 'val2'},None],
  [{'subkey1':'val3'}, {'subkey3':'val1'}, None, None]
]

final = defaultdict(dict)

for idx, key in enumerate(keys):
    for d in vals[idx]:
        if d is not None:
            final[key].update(d)

Output:

defaultdict(<class 'dict'>, {
 'key1': {'subkey1': 'val1', 'subkey2': 'val2'},
 'key2': {'subkey1': 'val2'},
 'key3': {'subkey1': 'val3', 'subkey3': 'val1'}
})

CodePudding user response:

can't use append on a dict try this maybe?

keys = ['key1', 'key2', 'key3']
vals = [[{'subkey1': 'val1', 'subkey2': 'val2'}], [{'subkey1': 'val2'},None],[{'subkey1':'val3'}, {'subkey3':'val1'}, None, None]]
s = {}
for i in keys:
    s[i] = {}
for i, key in enumerate(keys):
    for element in vals[i]:
        if isinstance(element, dict) == True:
            s[str(key)].update(element)
print(s)

Output:

{'key1': {'subkey1': 'val1', 'subkey2': 'val2'}, 'key2': {'subkey1': 'val2'}, 'key3': {'subkey1': 'val3', 'subkey3': 'val1'}}
  • Related