我想要两个词典并打印出它们的差异。此差异应包括键和值的差异。我已经创建了这个小片段,以使用unittest
模块中的内置代码来实现结果。然而,这是一个讨厌的黑客,因为我必须继承unittest.TestCase
并提供runtest()
方法才能工作。此外,此代码将导致应用程序出错,因为当存在差异时它将引发AssertError
。我真正想要的就是打印差异。
import unittest
class tmp(unittest.TestCase):
def __init__(self):
# Show full diff of objects (dicts could be HUGE and output truncated)
self.maxDiff = None
def runTest():
pass
_ = tmp()
_.assertDictEqual(d1, d2)
我希望使用difflib
模块,但它看起来只适用于字符串。有没有办法解决这个问题,仍然使用difflib
?
答案 0 :(得分:5)
改编自cpython来源:
import difflib
import pprint
def compare_dicts(d1, d2):
return ('\n' + '\n'.join(difflib.ndiff(
pprint.pformat(d1).splitlines(),
pprint.pformat(d2).splitlines())))
答案 1 :(得分:2)
您可以使用difflib,但使用unittest方法似乎更适合我。但是如果你想使用difflib。让我们说以下是两个词。
In [50]: dict1
Out[50]: {1: True, 2: False}
In [51]: dict2
Out[51]: {1: False, 2: True}
您可能需要将它们转换为字符串(或字符串列表),然后将difflib用作正常业务。
In [43]: a = '\n'.join(['%s:%s' % (key, value) for (key, value) in sorted(dict1.items())])
In [44]: b = '\n'.join(['%s:%s' % (key, value) for (key, value) in sorted(dict2.items())])
In [45]: print a
1:True
2:False
In [46]: print b
1:False
2:True
In [47]: for diffs in difflib.unified_diff(a.splitlines(), b.splitlines(), fromfile='dict1', tofile='dict2'):
print diffs
输出将是:
--- dict1
+++ dict2
@@ -1,2 +1,2 @@
-1:True
-2:False
+1:False
+2:True
答案 2 :(得分:1)
您可以使用.items()
和集合来执行以下操作:
>>> d = dict((i,i) for i in range(10))
>>> d2 = dict((i,i) for i in range(1,11))
>>>
>>> set(d.items()) - set(d2.items())
set([(0, 0)])
>>>
>>> set(d2.items()) - set(d.items())
set([(10, 10)])
>>>
>>> set(d2.items()) ^ set(d.items()) #symmetric difference
set([(0, 0), (10, 10)])
>>> set(d2.items()).symmetric_difference(d.items()) #only need to actually create 1 set
set([(0, 0), (10, 10)])
答案 3 :(得分:1)
我发现了一个名为datadiff的库(没有很好的文档),它在python中给出了可散列数据结构的差异。你可以使用pip或easy_install安装它。试一试!
答案 4 :(得分:0)
见Python recipe to create difference (as dictionary) of two dictionaries。你能描述一下输出应该是什么样的(请附上一个例子)吗?
答案 5 :(得分:0)
使用@ mgilson's solution并进一步说明OP请求使用unittest
模块。
def test_dict_diff(self):
dict_diff = list(set(self.dict_A.items()).symmetric_difference(set(self.dict_B.items()))))
fail_message = "too many differences:\nThe differences:\n" +
"%s" % "\n".join(dict_diff)
self.assertTrue((len(dict_diff) < self.maxDiff), fail_message)
答案 6 :(得分:0)
查看https://github.com/inveniosoftware/dictdiffer
print list(diff(
{2014: [
dict(month=6, category=None, sum=672.00),
dict(month=6, category=1, sum=-8954.00),
dict(month=7, category=None, sum=7475.17),
dict(month=7, category=1, sum=-11745.00),
dict(month=8, category=None, sum=-12140.00),
dict(month=8, category=1, sum=-11812.00),
dict(month=9, category=None, sum=-31719.41),
dict(month=9, category=1, sum=-11663.00),
]},
{2014: [
dict(month=6, category=None, sum=672.00),
dict(month=6, category=1, sum=-8954.00),
dict(month=7, category=None, sum=7475.17),
dict(month=7, category=1, sum=-11745.00),
dict(month=8, category=None, sum=-12141.00),
dict(month=8, category=1, sum=-11812.00),
dict(month=9, category=None, sum=-31719.41),
dict(month=9, category=1, sum=-11663.00),
]}))
给出了这个输出,我觉得非常棒:
[('change', ['2014', 4, 'sum'], (-12140.0, -12141.0))]
即。它给出了所发生的事情:一个价值&#34;改变了#34;路径&#34; [&#39; 2014&#39; 4,&#39; sum&#39;]&#34;并且它从-12140.0变为-12141.0。