2

I want to use dd1 and dd2 to update dd3

dd1 = {'a': {'b': [{'x':1}]}}
dd2 = {'a': {'c': [{'x':2}]}}
dd3 = {'a': {'b': {}, 'c': {}}}

so I get dd3:

dd3 = {'a': {'b': [{'x':1}], 'c': [{'x':2}]}}

I know how to update flat dictionary

d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'a': 2, 'b': 3, 'd': 4}

d3 = defaultdict(list)

for k, v in chain(d1.items(), d2.items()):
    d3[k].append(v)

but struggle to find clear way to update nested dictionary:

naivepredictor
  • 898
  • 4
  • 14

2 Answers2

1

With recursive traversal (assuming that all source dicts have same depth levels and lists as final expected update values):

dd1 = {'a': {'b': [{'x':1}]}}
dd2 = {'a': {'c': [{'x':2}]}}
dd3 = {'a': {'b': {}, 'c': {}}}

def update_nested_dict(target, d1, d2):
    for k,v in target.items():
        d1_v, d2_v = d1.get(k, []), d2.get(k, [])
        if isinstance(v, dict):
            if not v:
                target[k] = d1_v + d2_v
            else:
                update_nested_dict(v, d1_v, d2_v)

update_nested_dict(dd3, dd1, dd2)
print(dd3)

The output:

{'a': {'b': [{'x': 1}], 'c': [{'x': 2}]}}
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
  • what if I have more dictionaries e.g. dd1, dd2, ... , ddN to use to update dd_out (dd3) ? – naivepredictor Jul 26 '19 at 08:29
  • output dictionary may have multiple keys at each level because input dictionary could be e.g. {'g': {'b': [{'x':1}]}} so dd3 would have 'g' as second key at level 1 next to 'a'. dd3 = {'a': {'b': {}, 'c': {}}, 'g': {'b': {}}} – naivepredictor Jul 26 '19 at 08:44
  • 1
    @naivepredictor, ok, extend your input sample to reflect `ad.2` section, especially `number of dd1 nesting levels does not always equal to number of dd2 nesting levels` – RomanPerekhrest Jul 26 '19 at 09:07
1

You can use recursion:

dd1 = {'a': {'b': [{'x':1}]}}
dd2 = {'a': {'c': [{'x':2}]}}
dd3 = {'a': {'b': {}, 'c': {}}}
def update(d, *args):
    return {a:(lambda x:x[0] if not b else update(b, *x))([i[a] for i in args if a in i])\
            if isinstance(b, dict) else b for a, b in d.items()}

print(update(dd3, dd1, dd2))

Output:

{'a': {'b': [{'x': 1}], 'c': [{'x': 2}]}}

This solution can handle multiple dictionaries of varying depths:

dd1 = {'a': {'b':{'d':{'e':[{'x':1}]}}}}
dd2 = {'a': {'c': [{'x':2}]}}
dd4 = {'a':{'j':{'k':[{'x':3}]}}}
dd3 = {'a': {'b': {'d':{'e':{}}}, 'c': {}, 'j':{'k':{}}}}
print(update(dd3, dd1, dd2, dd4))

Output:

{'a': {'b': {'d': {'e': [{'x': 1}]}}, 'c': [{'x': 2}], 'j': {'k': [{'x': 3}]}}}
Ajax1234
  • 69,937
  • 8
  • 61
  • 102