use*_*312 222 python comparison dictionary
我有两个词典,但为了简化,我将采用这两个:
>>> x = dict(a=1, b=2)
>>> y = dict(a=2, b=2)
Run Code Online (Sandbox Code Playgroud)
现在,我想比较每key, value对中是否x具有相同的对应值y.所以我写了这个:
>>> for x_values, y_values in zip(x.iteritems(), y.iteritems()):
if x_values == y_values:
print 'Ok', x_values, y_values
else:
print 'Not', x_values, y_values
Run Code Online (Sandbox Code Playgroud)
它是有效的,因为tuple返回然后比较相等.
我的问题:
它是否正确?有更好的方法吗?更好的不是速度,我说的是代码优雅.
更新:我忘了提到我必须检查有多少key, value对是相等的.
Joc*_*zel 164
你想做的只是简单 x==y
你做的不是一个好主意,因为字典中的项目不应该有任何顺序.您可能正在[('a',1),('b',1)]与[('b',1), ('a',1)](相同的词典,不同的顺序)进行比较.
例如,看到这个:
>>> x = dict(a=2, b=2,c=3, d=4)
>>> x
{'a': 2, 'c': 3, 'b': 2, 'd': 4}
>>> y = dict(b=2,c=3, d=4)
>>> y
{'c': 3, 'b': 2, 'd': 4}
>>> zip(x.iteritems(), y.iteritems())
[(('a', 2), ('c', 3)), (('c', 3), ('b', 2)), (('b', 2), ('d', 4))]
Run Code Online (Sandbox Code Playgroud)
差异只是一个项目,但您的算法将看到所有项目都不同
mou*_*uad 163
如果你想知道两个词典中有多少个值匹配,你应该说:)
也许是这样的:
shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)
Run Code Online (Sandbox Code Playgroud)
Dan*_*ers 147
def dict_compare(d1, d2):
d1_keys = set(d1.keys())
d2_keys = set(d2.keys())
intersect_keys = d1_keys.intersection(d2_keys)
added = d1_keys - d2_keys
removed = d2_keys - d1_keys
modified = {o : (d1[o], d2[o]) for o in intersect_keys if d1[o] != d2[o]}
same = set(o for o in intersect_keys if d1[o] == d2[o])
return added, removed, modified, same
x = dict(a=1, b=2)
y = dict(a=2, b=2)
added, removed, modified, same = dict_compare(x, y)
Run Code Online (Sandbox Code Playgroud)
Ped*_*ito 95
dic1 == dic2从python文档:
为了说明这一点,下面的例子都将返回一个字典等于 到
{"one": 1, "two": 2, "three": 3}:Run Code Online (Sandbox Code Playgroud)>>> a = dict(one=1, two=2, three=3) >>> b = {'one': 1, 'two': 2, 'three': 3} >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3])) >>> d = dict([('two', 2), ('one', 1), ('three', 3)]) >>> e = dict({'three': 3, 'one': 1, 'two': 2}) >>> a == b == c == d == e True
适用于py2和py3.
phi*_*ipp 53
我是python的新手,但我最终做了类似于@mouad的事情
unmatched_item = set(dict_1.items()) ^ set(dict_2.items())
len(unmatched_item) # should be 0
Run Code Online (Sandbox Code Playgroud)
^当两个dicts中的dict相同时,XOR运算符()应该消除dict的所有元素.
小智 44
只需使用:
assert cmp(dict1, dict2) == 0
Run Code Online (Sandbox Code Playgroud)
Sum*_*udu 41
由于似乎没有人提及deepdiff,我将在这里添加它只是为了完整性.我发现一般来说获取(嵌套)对象的差异非常方便.
import deepdiff
import json
dict_1 = {
"a": 1,
"nested": {
"b": 1,
}
}
dict_2 = {
"a": 2,
"nested": {
"b": 2,
}
}
diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(diff, indent=4))
Run Code Online (Sandbox Code Playgroud)
输出:
{
"values_changed": {
"root['a']": {
"new_value": 2,
"old_value": 1
},
"root['nested']['b']": {
"new_value": 2,
"old_value": 1
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意:
deepdiff 需要安装包,因为这不是标准包
必须付出一些努力才能解析结果
但是,为了获取字典的差异,我觉得deepdiff非常方便.
小智 9
对两个字典进行深度比较的最简单方法(也是最可靠的方法之一)是以 JSON 格式序列化它们,对键进行排序,然后比较字符串结果:
import json
if json.dumps(x, sort_keys=True) == json.dumps(y, sort_keys=True):
... Do something ...
Run Code Online (Sandbox Code Playgroud)
@mouad的答案很好,如果你假设两个字典都只包含简单的值.但是,如果您有包含词典的词典,您将获得例外,因为词典不可清除.
在我的头顶,这样的事情可能会起作用:
def compare_dictionaries(dict1, dict2):
if dict1 is None or dict2 is None:
print('Nones')
return False
if (not isinstance(dict1, dict)) or (not isinstance(dict2, dict)):
print('Not dict')
return False
shared_keys = set(dict2.keys()) & set(dict2.keys())
if not ( len(shared_keys) == len(dict1.keys()) and len(shared_keys) == len(dict2.keys())):
print('Not all keys are shared')
return False
dicts_are_equal = True
for key in dict1.keys():
if isinstance(dict1[key], dict) or isinstance(dict2[key], dict):
dicts_are_equal = dicts_are_equal and compare_dictionaries(dict1[key], dict2[key])
else:
dicts_are_equal = dicts_are_equal and all(atleast_1d(dict1[key] == dict2[key]))
return dicts_are_equal
Run Code Online (Sandbox Code Playgroud)
另一种可能性,直到OP的最后一个注释,是比较倾倒为JSON的词组的哈希(SHA或MD).构造哈希的方式保证如果它们相等,源字符串也是相等的.这是非常快速和数学上的声音.
import json
import hashlib
def hash_dict(d):
return hashlib.sha1(json.dumps(d, sort_keys=True)).hexdigest()
x = dict(a=1, b=2)
y = dict(a=2, b=2)
z = dict(a=1, b=2)
print(hash_dict(x) == hash_dict(y))
print(hash_dict(x) == hash_dict(z))
Run Code Online (Sandbox Code Playgroud)
def equal(a, b):
type_a = type(a)
type_b = type(b)
if type_a != type_b:
return False
if isinstance(a, dict):
if len(a) != len(b):
return False
for key in a:
if key not in b:
return False
if not equal(a[key], b[key]):
return False
return True
elif isinstance(a, list):
if len(a) != len(b):
return False
while len(a):
x = a.pop()
index = indexof(x, b)
if index == -1:
return False
del b[index]
return True
else:
return a == b
def indexof(x, a):
for i in range(len(a)):
if equal(x, a[i]):
return i
return -1
Run Code Online (Sandbox Code Playgroud)
>>> a = {
'number': 1,
'list': ['one', 'two']
}
>>> b = {
'list': ['two', 'one'],
'number': 1
}
>>> equal(a, b)
True
Run Code Online (Sandbox Code Playgroud)
要测试两个字典的键和值是否相等:
def dicts_equal(d1,d2):
""" return True if all keys and values are the same """
return all(k in d2 and d1[k] == d2[k]
for k in d1) \
and all(k in d1 and d1[k] == d2[k]
for k in d2)
Run Code Online (Sandbox Code Playgroud)
如果要返回不同的值,请以不同的方式编写:
def dict1_minus_d2(d1, d2):
""" return the subset of d1 where the keys don't exist in d2 or
the values in d2 are different, as a dict """
return {k,v for k,v in d1.items() if k in d2 and v == d2[k]}
Run Code Online (Sandbox Code Playgroud)
你将不得不调用它两次,即
dict1_minus_d2(d1,d2).extend(dict1_minus_d2(d2,d1))
Run Code Online (Sandbox Code Playgroud)
IMO的功能很好,清晰直观。但是,为了给您(另一个)答案,这是我的努力:
def compare_dict(dict1, dict2):
for x1 in dict1.keys():
z = dict1.get(x1) == dict2.get(x1)
if not z:
print('key', x1)
print('value A', dict1.get(x1), '\nvalue B', dict2.get(x1))
print('-----\n')
Run Code Online (Sandbox Code Playgroud)
对您或其他任何人都可能有用。
编辑:
我已经创建了上面的一个递归版本。在其他答案中还没有看到
def compare_dict(a, b):
# Compared two dictionaries..
# Posts things that are not equal..
res_compare = []
for k in set(list(a.keys()) + list(b.keys())):
if isinstance(a[k], dict):
z0 = compare_dict(a[k], b[k])
else:
z0 = a[k] == b[k]
z0_bool = np.all(z0)
res_compare.append(z0_bool)
if not z0_bool:
print(k, a[k], b[k])
return np.all(res_compare)
Run Code Online (Sandbox Code Playgroud)
我正在使用这个在 Python 3 中非常适合我的解决方案
import logging
log = logging.getLogger(__name__)
...
def deep_compare(self,left, right, level=0):
if type(left) != type(right):
log.info("Exit 1 - Different types")
return False
elif type(left) is dict:
# Dict comparison
for key in left:
if key not in right:
log.info("Exit 2 - missing {} in right".format(key))
return False
else:
if not deep_compare(left[str(key)], right[str(key)], level +1 ):
log.info("Exit 3 - different children")
return False
return True
elif type(left) is list:
# List comparison
for key in left:
if key not in right:
log.info("Exit 4 - missing {} in right".format(key))
return False
else:
if not deep_compare(left[left.index(key)], right[right.index(key)], level +1 ):
log.info("Exit 5 - different children")
return False
return True
else:
# Other comparison
return left == right
return False
Run Code Online (Sandbox Code Playgroud)
它比较 dict、list 和任何其他自己实现“==”运算符的类型。如果你需要比较其他不同的东西,你需要在“if树”中添加一个新的分支。
希望有帮助。
对于Python3:
data_set_a = dict_a.items()
data_set_b = dict_b.items()
difference_set = data_set_a ^ data_set_b
Run Code Online (Sandbox Code Playgroud)
现在与 == 进行简单的比较就足够了(python 3.8)。即使您以不同的顺序比较相同的字典(最后一个例子)。最好的事情是,您不需要第三方软件包来完成此操作。
a = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
b = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
c = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
d = {'one': 'dog', 'two': 'cat', 'three': 'mouse', 'four': 'fish'}
e = {'one': 'cat', 'two': 'dog', 'three': 'mouse'}
f = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
g = {'two': 'cat', 'one': 'dog', 'three': 'mouse'}
h = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
print(a == b) # True
print(c == d) # False
print(e == f) # False
print(g == h) # True
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
388280 次 |
| 最近记录: |