2012-10-18 32 views
4

我想帶兩本詞典並打印它們的差異。這個差異應該包括鍵和值的差異。我已經創建了這個小片段來使用unittest模塊中的內置代碼實現結果。然而,這是一個令人討厭的黑客攻擊,因爲我必須繼承unittest.TestCase,並提供runtest()方法才能正常工作。另外,這段代碼會導致應用程序出錯,因爲當出現差異時它將引起AssertError。我真正想要的是打印差異。打印Python詞典的差異

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

的可能重複http://stackoverflow.com/questions/1165352/fast-comparison-between-two-python-dictionary –

+0

@MarkReed - 這是不同的。這要求*鍵*的差異,這要求*鍵*和*值*的差別(我假設OP需要*鍵值*對)。 「{1:2,2:3}」與「{1:3,2:2}」不同,但實際上並沒有明確說明...... – mgilson

+0

@mgilson - 我沒有提出關閉請求或將其標記爲重複,但如果您查看該頁面上的接受答案,則它包含值比較,而不僅僅是鍵集比較。 –

回答

1

您可以使用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 
+0

這看起來很酷。好主意。爲什麼你會說unittest方法在這裏更合適? –

+0

@ durden2.0 unittest方法似乎提供了一種更簡單的方法。沒有翻譯成字符串需要,等 –

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)]) 
0

Python recipe to create difference (as dictionary) of two dictionaries。你能描述一下輸出應該是什麼樣子嗎(請附上一個例子)?

+0

我沒有真正設置打印格式。我猜想看起來像標準的unidiff會很好。但是,assertDiffEqual()的打印並不差。下面是一些例子:AssertionError:{'a':'a'}!= {'a':'abc'} - {'a':'a'} + {'a':'abc'} ? ++ AssertionError:{'a':1}!= {'a':2} - {'a':1} ?^ + {'a':2} ?^ –

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) 
+0

這是非常整潔,但我認爲使用內置的'assertDictEqual()'是一個更好的解決方案,如果代碼已經使用'unittest'模塊。 –

+0

'assertDictEqual'在2.7+我使用2.6 ...所以我假設每個人都這樣做。 :但是,是的,那會更好用。 –

1

我發現了一個庫(不是非常有據可查)呼籲datadiff這給了哈希的數據結構的差異列表中的蟒蛇。您可以使用pip或easy_install進行安裝。試一試!

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))] 

即它給了什麼事:一個值 「改變」,路徑爲「[ '2014' ,4,'sum']「並且它從-12140.0改變爲-12141.0。