Разные многомерные словари в питоне - PullRequest
6 голосов
/ 16 ноября 2010

У меня есть два словаря

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 ]

4 голосов
/ 16 ноября 2010

В качестве начального ответа коленного рефлекса:

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']    
3 голосов
/ 03 октября 2014

Вы можете использовать мой пакет для 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"]}
1 голос
/ 16 ноября 2010

Вот очень простое решение. Он возвращает список списков, содержащий все ключи словаря первого и второго уровня для элементов, которые отличаются. Надеюсь, это то, что вы хотели:)

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

Ура! * * 1004

0 голосов
/ 29 октября 2013

Я не уверен, что это то, что вам нужно, но я нашел библиотеку, которая создает разницу между структурами данных Python. Он называется datadiff , и он в пять раз превышает различие между двумя словарями. я не уверен, что это даст вам разницу в «магазине», возможно, он покажет другое значение для всей «домашней» записи. Вы должны попробовать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...