在Python中比较多维字典

6 投票
4 回答
3146 浏览
提问于 2025-04-16 07:10

我有两个字典

a = {'home': {'name': 'Team1', 'score': 0}, 'away': {'name': 'Team2', 'score': 0}}
b = {'home': {'name': 'Team1', 'score': 2}, 'away': {'name': 'Team2', 'score': 0}}

这些字典的键是不会变的,但我想知道 ['home']['score'] 这个值有没有变化

有没有简单的方法可以做到这一点?

4 个回答

1

这里有一个非常简单的解决方案。它会返回一个列表,里面包含所有不同元素的第一层和第二层字典的键。希望这正是你想要的 :)

a = {'home':{'name': 'Team1', 'score': 0}, 'away':{'name': 'Team2', 'score': 0}}
b = {'home':{'name': 'Team1', 'score': 2}, 'away':{'name': 'Team2', 'score': 0}}

diffs = []
for i in a:
    for j in a[i]:
        if a[i][j] != b[i][j]:
            diffs += [i, j]

print diffs

谢谢!

3

你可以使用我为Python准备的这个包:

https://github.com/seperman/deepdiff

这个包不仅仅处理递归字典之间的差异:

安装

可以从PyPi安装:

pip install deepdiff

如果你使用的是Python3,还需要安装:

pip install future six

示例用法

>>> from deepdiff import DeepDiff
>>> from pprint import pprint
>>> from __future__ import print_function

相同的对象返回空值

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = t1
>>> ddiff = DeepDiff(t1, t2)
>>> print (ddiff.changes)
    {}

某个项目的类型发生了变化

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:"2", 3:3}
>>> ddiff = DeepDiff(t1, t2)
>>> print (ddiff.changes)
    {'type_changes': ["root[2]: 2=<type 'int'> vs. 2=<type 'str'>"]}

某个项目的值发生了变化

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:4, 3:3}
>>> ddiff = DeepDiff(t1, t2)
>>> print (ddiff.changes)
    {'values_changed': ['root[2]: 2 ====>> 4']}

项目被添加或移除

>>> t1 = {1:1, 2:2, 3:3, 4:4}
>>> t2 = {1:1, 2:4, 3:3, 5:5, 6:6}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff.changes)
    {'dic_item_added': ['root[5, 6]'],
     'dic_item_removed': ['root[4]'],
     'values_changed': ['root[2]: 2 ====>> 4']}

字符串之间的差异

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world"}}
>>> t2 = {1:1, 2:4, 3:3, 4:{"a":"hello", "b":"world!"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff.changes, indent = 2)
    { 'values_changed': [ 'root[2]: 2 ====>> 4',
                          "root[4]['b']:\n--- \n+++ \n@@ -1 +1 @@\n-world\n+world!"]}
>>>
>>> print (ddiff.changes['values_changed'][1])
    root[4]['b']:
    --- 
    +++ 
    @@ -1 +1 @@
    -world
    +world!

字符串之间的差异 2

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world!\nGoodbye!\n1\n2\nEnd"}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n1\n2\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff.changes, indent = 2)
    { 'values_changed': [ "root[4]['b']:\n--- \n+++ \n@@ -1,5 +1,4 @@\n-world!\n-Goodbye!\n+world\n 1\n 2\n End"]}
>>>
>>> print (ddiff.changes['values_changed'][0])
    root[4]['b']:
    --- 
    +++ 
    @@ -1,5 +1,4 @@
    -world!
    -Goodbye!
    +world
     1
     2
     End

类型变化

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":"world\n\n\nEnd"}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff.changes, indent = 2)
    { 'type_changes': [ "root[4]['b']: [1, 2, 3]=<type 'list'> vs. world\n\n\nEnd=<type 'str'>"]}

列表之间的差异

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff.changes, indent = 2)
    { 'list_removed': ["root[4]['b']: [3]"]}

列表之间的差异 2:注意,这里不考虑顺序

>>> # Note that it DOES NOT take order into account
... t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 3, 2]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff.changes, indent = 2)
    { }

包含字典的列表:

>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:1, 2:2}]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, {1:3}]}}
>>> ddiff = DeepDiff(t1, t2)
>>> pprint (ddiff.changes, indent = 2)
    { 'dic_item_removed': ["root[4]['b'][2][2]"],
      'values_changed': ["root[4]['b'][2][1]: 1 ====>> 3"]}
4

作为一个本能的初步反应:

a = {'home': {'name': 'Team1', 'score': 0}, 'away': {'name': 'Team2', 'score': 0}}
b = {'home': {'name': 'Team1', 'score': 2}, 'away': {'name': 'Team2', 'score': 0}}

def valchange(d1, d2, parent=''):
    changes=[]
    for k in d1.keys():
        if type(d1[k])==type({}):
            changes.extend(valchange(d1[k], d2[k], k))
        else:
            if d1[k]!=d2[k]:
                if parent=='':
                    changes.append(k + ' has changed ')
                else:
                    changes.append(parent + '.' + k + ' has changed')
    return changes

print valchange(a,b)

>>>
['home.score has changed']    

撰写回答