繁体   English   中英

测试dict中是否包含dict

[英]Test if dict contained in dict

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

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

print(first == second) # Result: True

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

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

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

编辑1:

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

编辑2:

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

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

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

谢谢你的回答!

您可以使用字典视图

# 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`

字典视图是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

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

>>> 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

您还可以将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`

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

all(k in second and second[k] == v for k, v in first.items())

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

all(second.get(k, None) == v for k, v in first.items())

所以,你基本上想要检查一个字典是否是另一个字典的子集。

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))

打印:

True

如果您想抽象出子集/超集部分:

def subset_dic(dict1, dict2):
    return len(set(dict1.items()) & set(dict2.items())) == len(min((dict1, dict2), key=len))

注意 :如果任何值是可变对象,则无法工作。 因此,您可以在函数中添加额外的步骤(将可变对象转换为不可变模拟)以克服此限制。

#Update Ans:

方法-1:使用字典视图:

正如Martijn所说,我们可以使用字典视图来检查这一点。 dict.viewitems()充当集合。 我们可以在此交叉,联合等上执行各种设置操作。(检查此链接 。)

first.viewitems() <= second.viewitems()
True

我们检查first是否小于等于second 评估为True意味着firstsecond.个子集second.

METHOD-2使用集合的issubset()操作:

(免责声明:此方法有一些冗余,并且要求所有值都是可清除的。建议遵循方法1来处理所有情况。感谢Martijn的建议。)

使用.items()属性获取(键,值)元组的列表,然后使用集合的issubset()操作。

这将检查键和相等。

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

>>> set(first.items()).issubset(second.items())
True

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM