3

Assume I have the following two dictionaries:

dict1 = 
{ 
   'battery1' : { 'Charge': 'enable', 'Discharge': 'enable' },
   'battery2' : { 'Charge': 'enable', 'Discharge': 'enable' }
}

dict2 = 
{
   'Estimated battery run-time': '05:00 minutes', 

   'battery1': {'Device': 'controller', 'Discharge': 'enable', 
   'Charging State': 'Fully charged', 'Charge': 'disable'}, 

   'battery2': {'Device': 'controller', 'Discharge': 'enable', 
   'Charging State': 'Fully charged', 'Charge': 'disable'}
}

I would like to check if dict1 is a subset of dict2 (i.e if the key value pairs in dict 1 are shown in dict2, while its OK that the same keys in dict2 will include EXTRA values like Charging state and Device).

for k, v in dict1.iteritems():
    for t, c in v.iteritems():
        if k in dict2:
            if c != dict2[k][v]:
                mismatch = true
                break;

But I get

unhashable type: 'dict' error. 

Note that this is a different question than:

Loop through all nested dictionary values?

Taking sums of nested values of nested dictionary

Iterate over nested dictionary

Can someone please assist?

Thanks in advance.

Community
  • 1
  • 1
Qwerty
  • 748
  • 1
  • 9
  • 25

2 Answers2

0

You had a few errors. If I understand what you need then this works for me. This is the python 3 version. For python 2, replace dict.items() with dict.iteritems().

def compare(dict1, dict2):
    for k1, v1 in dict1.items():
        if k1 in dict2:
            for k2, v2 in v1.items():
                if v2 != dict2[k1][k2]:
                    return False
    return True

for example, with these data

dict1 = {
   'battery1' : { 'Charge': 'enable', 'Discharge': 'enable' },
   'battery2' : { 'Charge': 'enable', 'Discharge': 'enable' }
}

dict2a = {
    'Estimated battery run-time': '05:00 minutes',
    'battery1': {
        'Device': 'controller',
        'Discharge': 'enable',
        'Charging State': 'Fully charged',
        'Charge': 'enable'
    },
    'battery2': {
        'Device': 'controller',
        'Discharge': 'enable',
        'Charging State': 'Fully charged',
        'Charge': 'enable'
    }
}

dict2b = {
    'Estimated battery run-time': '05:00 minutes',
    'battery1': {
        'Device': 'controller',
        'Discharge': 'enable',
        'Charging State': 'Fully charged',
        'Charge': 'disable'
    },
    'battery2': {
        'Device': 'controller',
        'Discharge': 'enable',
        'Charging State': 'Fully charged',
        'Charge': 'disable'
    }
}

running it for each dictionary produces the right answer (I think).

print(compare(dict1, dict2a)) # True
print(compare(dict1, dict2b)) # False
Graeme Stuart
  • 5,837
  • 2
  • 26
  • 46
  • 1
    why was this one downvoted? The solution works and does what the OP is asking for. – Dannid Jan 04 '18 at 19:15
  • btw, there is a potential flaw here in that keys in dict1 that are not present in dict2 would never be compared, making dict1 not truly a subset of dict2. Fix this by adding an `else: return False` to the `if k1 in dict2` test. – Dannid Jan 04 '18 at 19:28
0

I've had cause to compare partially nested dicts and lists and came up with this:

def compare_partial_nested_data(small, big):
    for skey in small:
        found = False
        for bkey in big:
            bval, sval = bkey, skey # list values are the keys
            if isinstance(small, dict) and isinstance(big, dict):
                bval, sval = big[bkey], small[skey] # replace values if dict
            if isinstance(sval, (dict, list)) and isinstance(bval, (dict, list)):
                found = compare_partial_nested_data(sval, bval)
            else:
                found = skey==bkey and sval==bval
            if found: break
        if not found: return False
    return True

Test:

find = {
    'zzz': [{'ccc': [{'ccc': 'ccc'}, 12345]}, 'abcde'],
    'xxx': 'xxx',
}
message = {
    'xxx': 'xxx',
    'yyy': 'yyy',
    'zzz': [
        {'aaa': 'aaa'},
        {'bbb': 'bbb'},
        {'ccc': [
            {'aaa': 'aaa'},
            {'bbb': 'bbb'},
            {'ccc': 'ccc'},
            12345,
        ]},
        {},
        [],
        67890,
        'abcde',
    ]
}
print(compare_partial_nested_dicts(find, message))
> True
Alan
  • 71
  • 3