测试dict中是否包含dict

swe*_*ber 33 python dictionary

对于python dicts,测试相等的工作正常如下:

first  = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois"}

print(first == second) # Result: True
Run Code Online (Sandbox Code Playgroud)

但现在我的第二个dict包含一些我想忽略的附加键:

first  = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法来测试第一个字典是否是第二个字典的一部分,包括它的所有键和值?

编辑1:

怀疑这个问题是如何测试字典是否包含某些的重复,但我对测试键及其值感兴趣.只包含相同的键不会使两个dicts相等.

编辑2:

好的,我现在用四种不同的方法得到了一些答案,证明了所有这些方法都有效.由于我需要一个快速的过程,我测试了每个执行时间.我创建了三个相同的词组,包含1000个项目,键和值是长度为10的随机字符串.second并且third获得了一些额外的键值对,并且third获得了新值的最后一个非额外键.所以,firstsecond,但不是的一部分third.使用timeit10000次重复的模块,我得到:

Method                                                      Time [s]   
first.viewitems() <=second.viewitems()                           0.9 
set(first.items()).issubset(second.items())                      7.3
len(set(first.items()) & set(second.items())) == len(first)      8.5
all(first[key] == second.get(key, sentinel) for key in first)    6.0
Run Code Online (Sandbox Code Playgroud)

我猜测最后一种方法是最慢的,但它已经到位2.但方法1击败了它们.

谢谢你的回答!

Mar*_*ers 57

您可以使用字典视图:

# 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`
Run Code Online (Sandbox Code Playgroud)

字典视图是Python 3中的标准,在Python 2中,您需要为标准方法添加前缀view.它们就像集合一样,并<=测试其中一个是否是另一个的子集(或等于).

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
Run Code Online (Sandbox Code Playgroud)

这也适用于不可散列的值,因为键使得键值对已经是唯一的.在这一点上,文档有点令人困惑,但即使使用可变值(例如,列表),这也有效:

>>> 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
Run Code Online (Sandbox Code Playgroud)

您还可以将该all()函数与生成器表达式一起使用; 使用object()作为定点简明检测缺失值:

sentinel = object()
if all(first[key] == second.get(key, sentinel) for key in first):
    # true only if `first` is a subset of `second`
Run Code Online (Sandbox Code Playgroud)

但这不像使用字典视图那样具有可读性和表现力.


beh*_*uri 7

all(k in second and second[k] == v for k, v in first.items())
Run Code Online (Sandbox Code Playgroud)

如果你知道没有任何值可以None,它将简化为:

all(second.get(k, None) == v for k, v in first.items())
Run Code Online (Sandbox Code Playgroud)