Is there a built-in function to say that dict A contains another dict B?

eg. dict a

contains dict b1

because:

a = { 'name': 'mary', 'age': 56, 'gender': 'female' }
b1 = { 'name': 'mary', 'age': 56 }

      

But this is False because the value for the key name

is different.

b2 = { 'name': 'elizabeth', 'age': 56 }

      

+3


source to share


4 answers


These are "short circuits". When the first element b2

that is not in is found a

, it all()

terminates immediately. Also avoids memory overhead when creating temporary sets

>>> a = { 'name': 'mary', 'age': 56, 'gender': 'female' }
>>> b1 = { 'name': 'mary', 'age': 56 }
>>> 
>>> all(a[k]==v for k,v in b1.iteritems())
True
>>> b2 = { 'name': 'elizabeth', 'age': 56 }
>>> all(a[k]==v for k,v in b2.iteritems())
False

      



In case it b

contains keys that are not in a

, you can use this

>>> all(a.get(k, object())==v for k,v in b2.iteritems())
False

      

+7


source


set(b1.iteritems()) <= set(a.iteritems())

      



<=

implements a subset relationship on objects set

. This works when both keys and values ​​in both dicts are hashed (strings, tuples and ints, lists are not).

+7


source


I'm going to answer if the dictionaries are compatible, so I changed the sample:

>>> test_compat = lambda d1, d2: all(d1[k]==d2[k] for k in set(d1) & set(d2))
>>> a = { 'name': 'mary', 'age': 56, 'gender': 'female' }
>>> b1 = { 'name': 'mary', 'age': 56, 'phone' : '555' }
>>> b2 = { 'name': 'elizabeth', 'age': 56 }
>>> test_compat(a, b1) 
True
>>> test_compat(a, b2)
False
>>> test_compat(b1, a)
True

      

set(d1) & set(d2)

is the intersection of all keys between two dictionaries. all

will be before any mismatch of the corresponding values.

+2


source


Yes there is a built-in function. dict.items()

returns a kind of dictionary that behaves the same as set

:

In [1]: a = { 'name': 'mary', 'age': 56, 'gender': 'female' }
   ...: b1 = { 'name': 'mary', 'age': 56 }
   ...: 

In [2]: b1.items() <= a.items()
Out[2]: True

In [3]: b2 = { 'name': 'elizabeth', 'age': 56 }

In [4]: b2.items() <= a.items()
Out[4]: False

      

The <

, <=

>=

and operators >

have the same meaning as for set

s.

In python2.7, you can access the views dict

using the method viewitems()

.

This is much better than directly converting the elements to set

(as in the other suggested answers) because:

  • It works with non-writable values:

    In [10]: a = {'a': [1]}
        ...: set(a.items()) <= set(a.items())
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-10-893acb4047c9> in <module>()
          1 a = {'a': [1]}
    ----> 2 set(a.items()) <= set(a.items())
    
    TypeError: unhashable type: 'list'
    
          

    While:

    In [11]: a.items() <= a.items()
    Out[11]: True
    
          

  • It is more memory efficient because it does not require any other allocations. Usage set

    can double the memory used.

  • It's faster (since it avoids the overhead of a new allocation).

Simple test with suggested solutions (in python2):

In [1]: a = {'a'+str(i): i for i in range(500000)}
   ...: b = a.copy()
   ...: 

In [2]: %timeit set(a.iteritems()) <= set(b.iteritems())
1 loops, best of 3: 810 ms per loop

In [3]: %timeit all(a[k]==v for k,v in b.iteritems())
10 loops, best of 3: 157 ms per loop

In [4]: %timeit all(a.get(k,object())==v for k,v in b.iteritems())
1 loops, best of 3: 237 ms per loop

In [5]: %timeit a.viewitems() <= b.viewitems()
10 loops, best of 3: 80.8 ms per loop

In [6]: def test_compat(d1, d2):
   ...:     return all(d1[k]==d2[k] for k in set(d1) & set(d2))
   ...: 
   ...: def test_compat2(d1, d2):
   ...:     return all(d1[k] == d2[k] for k in d1.viewkeys() & d2.viewkeys())
   ...: 

In [7]: %timeit test_compat(a, b)
1 loops, best of 3: 514 ms per loop

In [8]: %timeit test_compat2(a, b)
1 loops, best of 3: 500 ms per loop

      

viewitems()

about 2x faster than the second fastest solution.

0


source







All Articles