Home > Enterprise >  compare and filter the two nested dictionaries in python
compare and filter the two nested dictionaries in python

Time:06-10

I have two dictionaries listed below

old_dict = { {'laptop' : {'purchasedon': 10052022} , {'mobile' : {'purchasedon': 10052022} }
new_dict = { {'laptop' : {'purchasedon': 10062022} , {'mobile' : {'purchasedon': 10052022} , {'tab' : {'purchasedon': 10062022}  }

I want to compare new dictionary with the old one with following conditions.

  1. new_dict has different key's (new key's)
  2. new_dict old keys values has been changed
  3. Remove if the key and values are same

Filter and create new dictionary based on above conditions.

Expected Output :

final_dict = { {'laptop' : {'purchasedon': 10062022}  , {'tab' : {'purchasedon': 10062022}  }

My Code

    final_dict = {}
    for k1, v1 in new_dict.items():  # the basic way
      if new_dict[k1]['purchaseon'] != old_dict[k1]['purchaseon']:
         final_dict = {k1: {'purchaseon': v1}}

I am getting key error. i don't know how to escape from it

CodePudding user response:

Assuming you actually have a dict of dict, and not a set of dict of dict. The latter is not possible in Python, and the former also conforms more to your existing code.

>>> old_dict = {'laptop': {'purchasedon': 10052022}, 'mobile': {'purchasedon': 10052022}}
>>> new_dict = {'laptop': {'purchasedon': 10062022}, 'mobile': {'purchasedon': 10052022}, 'tab': {'purchasedon': 10062022}}

To fix the KeyError, you have to first check if the key is in old_dict before trying to access it. Also note that with final_dict = ... in the if, you overwrite the entire dict. You probably want final_dict[k1] = v1 to insert just that element (v1 is already the entire inner dict).

final_dict = {}
for k, v in new_dict.items():
    if k not in old_dict or old_dict[k]['purchasedon'] != v['purchasedon']:
        final_dict[k] = v

You can also do so in a dict comprehension:

>>> {k: v for k, v in new_dict.items() if k not in old_dict or old_dict[k]['purchasedon'] != v['purchasedon']}
{'laptop': {'purchasedon': 10062022}, 'tab': {'purchasedon': 10062022}}

If you do not actually want to compare only by purchasedon, you may also use this variant:

>>> {k: v for k, v in new_dict.items() if k not in old_dict or old_dict[k] != v}
{'laptop': {'purchasedon': 10062022}, 'tab': {'purchasedon': 10062022}}

Assuming new_dict does not contain None values, you may also use dict.get to get the value from old_dict if it exists, or None (and not an exception) if it does not.

>>> {k: v for k, v in new_dict.items() if old_dict.get(k) != v}
{'laptop': {'purchasedon': 10062022}, 'tab': {'purchasedon': 10062022}}

CodePudding user response:

I assume the dict representation you made in the question is invalid, and probably looks something like

old_dict = {'laptop': {'purchasedon': 10052022}, 'mobile': {'purchasedon': 10052022}}
new_dict = {'laptop': {'purchasedon': 10062022}, 'mobile': {'purchasedon': 10052022},
                'tab': {'purchasedon': 10062022}}

You can compare the dicts for equality, and so a simple approach can be done something like below

# Find new keys!
new_keys = set(new_dict.keys()) - set(old_dict.keys())

# For a dict, with all new keys
final_dict = {new_key: new_dict.get(new_key) for new_key in new_keys}

# Find all records, which are not equal in both set of keys
modified_records = {ex_key: new_dict.get(ex_key) for ex_key in old_dict if
                    new_dict.get(ex_key) != old_dict.get(ex_key)}

# Create the final dict
final_dict.update(modified_records)

This can give you the output similar to your need

{"tab": {"purchasedon": 10062022}, "laptop": {"purchasedon": 10062022}}
  • Related