是否有内置功能说dict A包含另一个词典B?

时间:2012-03-26 10:07:41

标签: python

e.g。 dict a包含dict b1,因为:

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

但这是假的,因为键name的值不同。

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

4 个答案:

答案 0 :(得分:7)

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

<=set objects上实现子集关系。当两个dicts中的键和值都可以清除时(字符串,元组和整数都是,列表不是),这都可以工作。

答案 1 :(得分:7)

这是“短路”。当找到b2中不在a中的all()的第一项时,>>> 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 会立即终止。还避免了创建临时集的内存开销

b

如果a包含不在>>> all(a.get(k, object())==v for k,v in b2.iteritems()) False 中的密钥,则可以使用此

{{1}}

答案 2 :(得分:2)

如果词典兼容我会回答,所以我改变了样本:

>>> 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)是两个词典之间所有键的交集。 all会提前退出任何相应的值不匹配。

答案 3 :(得分:0)

有内置功能。 dict.items()返回字典视图,其行为与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

运营商<<= >=>set的含义相同。

在python2.7中,您可以使用viewitems()方法访问dict的视图。

这比明确将项目转换为set(如其他建议的答案中)要好得多,因为:

  • 它适用于不可用的值:

    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'
    

    虽然:

    In [11]: a.items() <= a.items()
    Out[11]: True
    
  • 它更节省内存,因为它不需要任何其他分配。使用set 可能加倍使用的内存。

  • 它更快(因为它避免了新分配的开销)。

使用建议的解决方案(在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()比第二快的解决方案快2倍。