Python 有没有更好的方法来比较字典值

Python 有没有更好的方法来比较字典值,python,dictionary,Python,Dictionary,我目前正在使用以下函数比较字典值。有没有更快或更好的方法 match = True for keys in dict1: if dict1[keys] != dict2[keys]: match = False print keys print dict1[keys], print '->' , print dict2[keys] 编辑:两个dict都包含相同的键。如果只是比较是否相等,可以执行以下

我目前正在使用以下函数比较字典值。有没有更快或更好的方法

match = True
for keys in dict1:
    if dict1[keys] != dict2[keys]:
        match = False
        print keys
        print dict1[keys],
        print  '->' ,
        print dict2[keys]

编辑:两个dict都包含相同的键。

如果只是比较是否相等,可以执行以下操作:

if not dict1 == dict2:
    match = False
否则,我看到的唯一主要问题是,如果dict1中有一个键不在dict2中,那么您将得到一个KeyError,因此您可能需要执行以下操作:

for key in dict1:
    if not key in dict2 or dict1[key] != dict2[key]:
        match = False
您可以将其压缩为一种理解,以获得不匹配的键列表:

mismatch_keys = [key for key in x if not key in y or x[key] != y[key]]
match = not bool(mismatch_keys) #If the list is not empty, they don't match 
for key in mismatch_keys:
    print key
    print '%s -> %s' % (dict1[key],dict2[key])

我能想到的唯一其他优化可能是使用“len(dict)”来找出哪个dict具有较少的条目,并首先循环该条目以获得尽可能短的循环。

嗯,您正在描述
dict1==dict2
(检查两个dict是否相等)

>>> a = {'x': 1, 'y': 2}
>>> b = {'y': 2, 'x': 1}
>>> print a == b
True
>>> c = {'z': 1}
>>> print a == c
False
>>> 

但是您的代码所做的是
all(dict1[k]==dict2[k]表示dict1中的k)
(检查dict1中的所有条目是否与dict2中的条目相同)

如果dict1中的键集相同,并且您需要所有这些打印以获得任何值差异,那么您就无能为力了;可能是这样的:

diffkeys = [k for k in dict1 if dict1[k] != dict2[k]]
for k in diffkeys:
  print k, ':', dict1[k], '->', dict2[k]

与您所拥有的几乎相同,但您可能会获得更好的演示文稿,例如,在循环之前对diffkey进行排序。

您也可以使用集合来完成此操作

>>> a = {'x': 1, 'y': 2}
>>> b = {'y': 2, 'x': 1}
>>> set(a.iteritems())-set(b.iteritems())
set([])
>>> a['y']=3
>>> set(a.iteritems())-set(b.iteritems())
set([('y', 3)])
>>> set(b.iteritems())-set(a.iteritems())
set([('y', 2)])
>>> set(b.iteritems())^set(a.iteritems())
set([('y', 3), ('y', 2)])

如果问题的真正目的是比较不同的口述(而不是打印差异),答案是

dict1 == dict2
这一点之前已经提到过,但我觉得它有点淹没在其他信息中。这可能看起来很肤浅,但dicts的价值比较实际上具有强大的语义。它涵盖

  • 键数(如果它们不匹配,则DICT不相等)
  • 键的名称(如果不匹配,则不相等)
  • 每个键的值(它们也必须是“==”)
最后一点再次显得微不足道,但非常有趣,因为它意味着所有这些也递归地应用于嵌套的dict。例如

 m1 = {'f':True}
 m2 = {'f':True}
 m3 = {'a':1, 2:2, 3:m1}
 m4 = {'a':1, 2:2, 3:m2}
 m3 == m4  # True

对于列表的比较,也存在类似的语义。所有这些都使比较深层Json结构变得非常简单,例如,单独使用简单的“==”

比较深层Json结构。如果您的字典嵌套很深,并且包含不同类型的集合,则可以将其转换为Json字符串并进行比较

import json
match = (json.dumps(dict1) == json.dumps(dict2))

警告-如果您的字典的值中有二进制字符串,则此解决方案可能不起作用,因为这不是json可序列化的

不确定这是否有帮助,但在我的应用程序中,我必须检查字典是否已更改

这样做是行不通的,因为基本上它仍然是同一个对象:

val={'A':1,'B':2}
old_val=val

val['A']=10
if old_val != val:
  print('changed')
使用copy/deepcopy works:

import copy
val={'A':1,'B':2}
old_val=copy.deepcopy(val)

val['A']=10
if old_val != val:
  print('changed')

如果您的值是可散列的(即字符串),那么您可以简单地比较两个dict的ItemsView

您可以使用任何
set
操作

因为在这种情况下您可能不关心键,所以您也可以只使用ValuesView(同样,如果值是可散列的)



需要一点澄清…您是否试图确定dict1和dict2是否包含完全相同的内容?或者dict2可以包含dict1中没有的其他值吗?另外,您需要能够显示所有不匹配的键吗?我需要能够显示所有不匹配的值。Dict2和dict1的键是一样的,这就是我当时要写的内容。您可以在一行上打印dict1[keys]、“->”和dict2[keys]。这里有一个用于显示差异的实用程序:它忽略了dict2比dict1有更多键的情况,因此它们的行为实际上并不相同。除非其中一个值是不可损坏的(例如,
列表
set({'x':[]}.iteritems())
将引发
TypeError
@user212218-对于具有不可损坏对象的字典项,请参见此处:
所有这些都递归地应用于嵌套的dict,以及
是否明确记录了这一点,除了对复杂嵌套结构的任何限制(例如dict of list of dict等)之外,我想不出有哪一份文档能够准确地描述这一点。我的答案来自经验和实验。我向您推荐同样的方法,例如对您感兴趣的一些数据结构进行测试比较。哇,这是真的-
==
进行深入比较,至少对基本类型是这样!在REPL:
a={“a”:False,'b':[1,2,{'foo':'bar','zamboni':True,'cheese':[False,[]},3],'c]:None};b={'c':无,'a':假,'b':[1,2,{'cheese':[False,[]],'foo':'bar','zamboni':真},3]};a==b
。酷!我也没有发现
的官方文档递归地应用于嵌套的dict
部分,但是,不管它有什么价值,2个dict的
=
相等性比较是在中正式承诺的,而且您还可以搜索“映射(dict实例)比较相等”在这种情况下。如果每个元素都得到
=
测试,并且任何元素都可以是dict,那么它当然会递归地应用于嵌套dict。
match=not(dict1==dict2)
?@vinntec不只是
dict1!=dict2
?我建议更多,以避免模式
如果条件为True,否则为False
。除此之外,根据语言和涉及的类型,有时
not(=)
不同=
set_with_unique_key_value_pairs = dict1.items() ^ dict2.items()
set_with_matching_key_value_pairs = dict1.items() & dict2.items()
set_with_matching_values = dict1.values() & dict2.values()