Testing for equality works fine like this for python dicts:
first = {\"one\":\"un\", \"two\":\"deux\", \"three\":\"trois\"}
second = {\"one\":\"un\", \"two\
So, you basically want to check if one dictionary is a subset of another.
first = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
def subset_dic(subset, superset):
return len(set(subset.items()) & set(superset.items())) == len(subset)
print(subset_dic(first, second))
Prints:
True
In case you want to abstract out the subset/superset part:
def subset_dic(dict1, dict2):
return len(set(dict1.items()) & set(dict2.items())) == len(min((dict1, dict2), key=len))
Note: this will fail to work, if any value is a mutable object. Hence you can add an additional step (convert mutable object to immutable analog) in the function to overcome this limitation.
You can use a dictionary view:
# Python 2
if first.viewitems() <= second.viewitems():
# true only if `first` is a subset of `second`
# Python 3
if first.items() <= second.items():
# true only if `first` is a subset of `second`
Dictionary views are the standard in Python 3, in Python 2 you need to prefix the standard methods with view
. They act like sets, and <=
tests if one of those is a subset of (or is equal to) another.
Demo in Python 3:
>>> first = {"one":"un", "two":"deux", "three":"trois"}
>>> second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
>>> first.items() <= second.items()
True
>>> first['four'] = 'quatre'
>>> first.items() <= second.items()
False
This works for non-hashable values too, as the keys make the key-value pairs unique already. The documentation is a little confusing on this point, but even with mutable values (say, lists) this works:
>>> first_mutable = {'one': ['un', 'een', 'einz'], 'two': ['deux', 'twee', 'zwei']}
>>> second_mutable = {'one': ['un', 'een', 'einz'], 'two': ['deux', 'twee', 'zwei'], 'three': ['trois', 'drie', 'drei']}
>>> first_mutable.items() <= second_mutable.items()
True
>>> first_mutable['one'].append('ichi')
>>> first_mutable.items() <= second_mutable.items()
False
You could also use the all() function with a generator expression; use object()
as a sentinel to detect missing values concisely:
sentinel = object()
if all(first[key] == second.get(key, sentinel) for key in first):
# true only if `first` is a subset of `second`
but this isn't as readable and expressive as using dictionary views.
all(k in second and second[k] == v for k, v in first.items())
if you know that none of the values can be None
, it will simplify to:
all(second.get(k, None) == v for k, v in first.items())
# Updated Ans:
METHOD-1: Using Dictionary Views:
As Martijn suggested, We can use dictionary views to check this. dict.viewitems()
acts as a set. We can perform various set operations on this like intersection, union etc. (Check this link.)
first.viewitems() <= second.viewitems()
True
We check if first
is less than equal to second
. This evaluating to True means first
is a subset of second.
METHOD-2 Using issubset() operation of sets:
(DISCLAIMER: This method has some redundancy and requires all values to be hashable. Method-1 is suggested to be followed to handle all cases. Thanks Martijn for the suggestions.)
Use .items()
attribute of a dictionary to get a list of (key,value) tuples and then use issubset() operation of sets.
This will check for both the keys and the equality..
>>> first = {"one":"un", "two":"deux", "three":"trois"}
>>> second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
>>> set(first.items()).issubset(second.items())
True