Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if one dictionary is a subset of another larger dictionary?

People also ask

How do you know if a dictionary is subset of another?

Both sets have one element: One has the key value tuple "name":"Girls" and the other has the single element composed of a key value tuple "show": {"name": "Girls"} and when two sets both have one element, those elements must be equal for the sets to be considered subsets of eachother.

Can a dictionary contain another dictionary?

Both can be nested. A list can contain another list. A dictionary can contain another dictionary. A dictionary can also contain a list, and vice versa.

How do I check if two dictionaries are equal in Python?

The simplest technique to check if two or multiple dictionaries are equal is by using the == operator in Python. You can create the dictionaries with any of the methods defined in Python and then compare them using the == operator. It will return True the dictionaries are equals and False if not.


In Python 3, you can use dict.items() to get a set-like view of the dict items. You can then use the <= operator to test if one view is a "subset" of the other:

d1.items() <= d2.items()

In Python 2.7, use the dict.viewitems() to do the same:

d1.viewitems() <= d2.viewitems()

In Python 2.6 and below you will need a different solution, such as using all():

all(key in d2 and d2[key] == d1[key] for key in d1)

Convert to item pairs and check for containment.

all(item in superset.items() for item in subset.items())

Optimization is left as an exercise for the reader.


Note for people that need this for unit testing: there's also an assertDictContainsSubset() method in Python's TestCase class.

http://docs.python.org/2/library/unittest.html?highlight=assertdictcontainssubset#unittest.TestCase.assertDictContainsSubset

It's however deprecated in 3.2, not sure why, maybe there's a replacement for it.


For completeness, you can also do this:

def is_subdict(small, big):
    return dict(big, **small) == big

However, I make no claims whatsoever concerning speed (or lack thereof) or readability (or lack thereof).

Update: As pointed out by Boris' comment, this trick does not work if your small dict has non-string keys and you're using Python >= 3 (or in other words: in the face of arbitrarily typed keys, it only works in legacy Python 2.x).

If you are using Python 3.9 or newer, though, you can make it work both with non-string typed keys as well as get an even neater syntax.

Provided your code already has both dictionaries as variables, it's very concise to check for this inline:

if big | small == big:
    # do something

Otherwise, or if you prefer a reusable function as above, you can use this:

def is_subdict(small, big):
    return big | small == big

The working principle is the same as the first function, only this time around making use of the union operator that was extended to support dicts.


for keys and values check use: set(d1.items()).issubset(set(d2.items()))

if you need to check only keys: set(d1).issubset(set(d2))


>>> d1 = {'a':'2', 'b':'3'}
>>> d2 = {'a':'2', 'b':'3','c':'4'}
>>> all((k in d2 and d2[k]==v) for k,v in d1.iteritems())
True

context:

>>> d1 = {'a':'2', 'b':'3'}
>>> d2 = {'a':'2', 'b':'3','c':'4'}
>>> list(d1.iteritems())
[('a', '2'), ('b', '3')]
>>> [(k,v) for k,v in d1.iteritems()]
[('a', '2'), ('b', '3')]
>>> k,v = ('a','2')
>>> k
'a'
>>> v
'2'
>>> k in d2
True
>>> d2[k]
'2'
>>> k in d2 and d2[k]==v
True
>>> [(k in d2 and d2[k]==v) for k,v in d1.iteritems()]
[True, True]
>>> ((k in d2 and d2[k]==v) for k,v in d1.iteritems())
<generator object <genexpr> at 0x02A9D2B0>
>>> ((k in d2 and d2[k]==v) for k,v in d1.iteritems()).next()
True
>>> all((k in d2 and d2[k]==v) for k,v in d1.iteritems())
True
>>>