John Holmes
John Holmes

Reputation: 391

Performing calculations on multiple nested python dictionaries

Trying to create a dict comprehension by comparing two nested dictionaries of similar size and subtracting the last value of the lowest nested dictionary. Only values != 0 will be included in the dictionary.

d1 = {1: {'a':10,'b':20,'c':10}}
d2 = {1: {'a':30,'b':40,'c':10}}

matchKeys = d1.keys() & d2.keys()

new = {}
for k in matching_keys:
    if not d1[k] == d2[k]:
        for d1_key, d1_value in d1[k].items():
            for d2_key, d2_value  in d2[k].items():
                new[k][d2_key] = (d2_value-d1_value)

also tried:

d3 = {k: {d2_key:(d2_value-d1_value) for d2_key, d2_value in d2.items()} for d1_key, d1_value in d1[k].items() for k in matching_keys if not d1[k] == d2[k]}

I'm expecting:

d3 = {1: {'a':20,'b':20}}

Upvotes: 0

Views: 610

Answers (1)

Mark
Mark

Reputation: 92460

Your variable matchkeys only holds the keys on the first level of the dicts. You need to to get the keys of each level as you move into the dictionaries. It might be easier to think of this as a recursive function. Then you can just pass the nested dicts back into the function.

Something like:

d1 = {1: {'a':10,'b':20,'c':10}}
d2 = {1: {'a':30,'b':40,'c':10}}

def filterDifs(d1, d2):
    d = {}
    matchKeys = d1.keys() & d2.keys()
    for k in matchKeys:
        if isinstance(d1[k], dict) and isinstance(d2[k], dict):
            d[k] = filterDifs(d1[k], d2[k])
        else:
            try:
                if d1[k] - d2[k] != 0:
                    d[k] = d1[k] - d2[k]
            except TypeError:
                pass
    return d

filterDifs(d1, d2)

Result:

{1: {'b': -20, 'a': -20}}

This will ignore attempts to subtract incompatible types, but if you wanted to add some sort of value in those cases you could in the except block:

except TypeError:
    d[k] = "Some error value"

Upvotes: 1

Related Questions