首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >测试dict中是否包含dict

测试dict中是否包含dict
EN

Stack Overflow用户
提问于 2015-06-13 12:30:35
回答 4查看 25.7K关注 0票数 42

对于python来说,对等式的测试工作得很好,就像这样:

代码语言:javascript
复制
first  = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois"}

print(first == second) # Result: True

但是,现在我的第二个切分包含了一些我想忽略的额外键:

代码语言:javascript
复制
first  = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}

是否有一种简单的方法来测试第一个dict是否是第二个dict的一部分,以及它的所有键和值?

编辑1:

这个问题被怀疑是如何测试字典是否包含的重复,但我对测试键及其值很感兴趣。仅仅包含相同的键并不能使两个切分相等。

编辑2:

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

代码语言:javascript
复制
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胜过所有的方法。

谢谢你的回答!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-06-13 12:41:49

您可以使用字典视图

代码语言:javascript
复制
# 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中的标准,在Python2中,需要用view作为标准方法的前缀。它们的作用类似于集合,如果其中一个子集是(或等于)另一个子集,则进行<=测试。

Python 3中的演示:

代码语言:javascript
复制
>>> 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

这也适用于不可接受的值,因为键使得键值对已经是唯一的。文档在这一点上有点混乱,但即使对于可变的值(例如,列表),这也是可行的:

代码语言:javascript
复制
>>> 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

您还可以将函数与生成器表达式一起使用;使用object()作为哨兵,简明地检测缺少的值:

代码语言:javascript
复制
sentinel = object()
if all(first[key] == second.get(key, sentinel) for key in first):
    # true only if `first` is a subset of `second`

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

票数 81
EN

Stack Overflow用户

发布于 2015-06-13 12:40:06

代码语言:javascript
复制
all(k in second and second[k] == v for k, v in first.items())

如果您知道所有的值都不能是None,那么它将简化为:

代码语言:javascript
复制
all(second.get(k, None) == v for k, v in first.items())
票数 7
EN

Stack Overflow用户

发布于 2015-06-13 12:37:24

因此,您基本上想要检查一个字典是否是另一个字典的子集。

代码语言:javascript
复制
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))

指纹:

代码语言:javascript
复制
True

如果要抽象出子集/超集部分,请执行以下操作:

代码语言:javascript
复制
def subset_dic(dict1, dict2):
    return len(set(dict1.items()) & set(dict2.items())) == len(min((dict1, dict2), key=len))

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30818694

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档