提问人:John P 提问时间:8/26/2017 更新时间:10/23/2019 访问量:1292
Python中字典的严格比较
Strict Comparison of Dictionaries in Python
问:
我在比较两个相似的词典时遇到了一些麻烦。我想对值(可能还有键)进行更严格的比较。
这是真正基本的问题:
>>> {'a': True} == {'a': 1}
True
类似地(有点令人困惑):
>>> {1: 'a'} == {True: 'a'}
True
这是有道理的,因为.我正在寻找的是行为更像的东西,但比较了两个可能的嵌套字典。显然,您不能在两个字典上使用 use,因为即使所有元素都相同,它也会始终返回 。True == 1
is
is
False
我目前的解决方案是只用于获取两者的字符串表示并进行比较。json.dumps
>>> json.dumps({'a': True}, sort_keys=True) == json.dumps({'a': 1}, sort_keys=True)
False
但这只有在一切都是 JSON 可序列化的情况下才有效。
我还尝试手动比较所有键和值:
>>> l = {'a': True}
>>> r = {'a': 1}
>>> r.keys() == l.keys() and all(l[key] is r[key] for key in l.keys())
False
但是,如果字典具有一些嵌套结构,则此操作将失败。我想我可以写一个递归版本来处理嵌套的情况,但它似乎不必要地丑陋且不合时宜。
有没有“标准”或简单的方法来做到这一点?
谢谢!
答:
可用于在常规词典条目和嵌套词典条目之间进行界定。这样一来,你就可以遍历 using 来严格比较,但也可以检查何时需要向下潜入嵌套字典。isinstance()
is
https://docs.python.org/3/library/functions.html#isinstance
myDict = {'a': True, 'b': False, 'c': {'a': True}}
for key, value in myDict.items():
if isinstance(value, dict):
# do what you need to do....
else:
# etc...
评论
isinstance(myDict, dict)
:..myDict -> myDict[x] ?
for x, y in myDict.items()
您可以按元素测试所有(键、值)对的身份:
def equal_dict(d1, d2):
return all((k1 is k2) and (v1 is v2)
for (k1, v1), (k2, v2) in zip(d1.items(), d2.items()))
>>> equal_dict({True: 'a'}, {True: 'a'})
True
>>> equal_dict({1: 'a'}, {True: 'a'})
False
这应该适用于 、 和 ,但不适用于其他序列或更复杂的对象。
无论如何,如果你需要它,这是一个开始。float
int
str
bool
评论
is
'a'
你对 JSON 非常接近:改用 Python 的模块。这记录了在 Python 2.5+ 和 3 中对字典进行排序:pprint
在计算显示之前,字典按键排序。
让我们确认这一点。下面是 Python 3.6 中的一个会话(即使对于常规对象,它也能方便地保留插入顺序):dict
Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a = {2: 'two', 3: 'three', 1: 'one'}
>>> b = {3: 'three', 2: 'two', 1: 'one'}
>>> a
{2: 'two', 3: 'three', 1: 'one'}
>>> b
{3: 'three', 2: 'two', 1: 'one'}
>>> a == b
True
>>> c = {2: 'two', True: 'one', 3: 'three'}
>>> c
{2: 'two', True: 'one', 3: 'three'}
>>> a == b == c
True
>>> from pprint import pformat
>>> pformat(a)
"{1: 'one', 2: 'two', 3: 'three'}"
>>> pformat(b)
"{1: 'one', 2: 'two', 3: 'three'}"
>>> pformat(c)
"{True: 'one', 2: 'two', 3: 'three'}"
>>> pformat(a) == pformat(b)
True
>>> pformat(a) == pformat(c)
False
>>>
让我们快速确认一下,漂亮的打印对嵌套词典进行了排序:
>>> a['b'] = b
>>> a
{2: 'two', 3: 'three', 1: 'one', 'b': {3: 'three', 2: 'two', 1: 'one'}}
>>> pformat(a)
"{1: 'one', 2: 'two', 3: 'three', 'b': {1: 'one', 2: 'two', 3: 'three'}}"
>>>
因此,不要序列化为 JSON,而是使用 .我想可能有一些极端情况,你想认为不相等的两个对象仍然会创建相同的漂亮印刷表示。但这些情况应该很少见,你想要一些简单和 Pythonic 的东西,就是这样。pprint.pformat()
我想你正在寻找这样的东西。但是,由于您没有提供示例数据,因此我不会猜测它可能是什么
from boltons.itertools import remap
def compare(A, B): return A == B and type(A) == type(B)
dict_to_compare_against = { some dict }
def visit(path, key, value):
cur = dict_to_compare_against
for i in path:
cur = cur[i]
if not compare(cur, value):
raise Exception("Not equal")
remap(other_dict, visit=visit)
评论
is
True
1
JSONField
{"assembly_required": True}
{"assembly_required": 1}
DeepDiff(left, right) == {}