Confrontando due dizionari e controllando quante coppie (chiave, valore) sono uguali


246

Ho due dizionari, ma per semplificazione, prenderò questi due:

>>> x = dict(a=1, b=2)
>>> y = dict(a=2, b=2)

Ora, voglio confrontare se ogni key, valuecoppia in xha lo stesso valore corrispondente in y. Quindi ho scritto questo:

>>> for x_values, y_values in zip(x.iteritems(), y.iteritems()):
        if x_values == y_values:
            print 'Ok', x_values, y_values
        else:
            print 'Not', x_values, y_values

E funziona da quando tupleviene restituito a e quindi confrontato per l'uguaglianza.

Le mie domande:

È corretto? C'è un modo migliore per farlo? Meglio non in velocità, sto parlando di eleganza del codice.

AGGIORNAMENTO: ho dimenticato di dire che devo controllare quante key, valuecoppie sono uguali.


21
x == ydovrebbe essere vero in base alle stackoverflow.com/a/5635309/186202
TmpNR

x == y dovrebbe essere vero. Si può verificare rapidamente REPL. Si prega di fare riferimento: docs.python.org/2/library/stdtypes.html#mapping-types-dict
Vikrant

Risposte:


179

Se vuoi sapere quanti valori corrispondono in entrambi i dizionari, avresti dovuto dirlo :)

Forse qualcosa del genere:

shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)

1
Stesso errore se esiste un elemento elenco per la chiave dict. Penso che cmp sia il modo migliore per farlo a meno che non mi manchi qualcosa.
Mutante,

@Mutant è un problema diverso. In listprimo luogo non è possibile creare un dizionario con una chiave. x = {[1,2]: 2}avrà esito negativo. La domanda è già valida dicts.
AnnanFay,

@annan: sbagliato, la domanda è generica. l' esempio nella descrizione della domanda ha già "dicts validi". Se inserisco una nuova domanda, con lo stesso titolo, ma con un dict "non valido" diverso, qualcuno lo contrassegnerà come duplicato. Downvoting.
Ribamar,

6
@ribamar la domanda è "Confronto tra due dizionari [...]". Il 'dict non valido' sopra con le listchiavi non è un codice python valido - le chiavi dict devono essere immutabili. Pertanto non stai confrontando i dizionari. Se si tenta di utilizzare un elenco come chiave del dizionario, il codice non verrà eseguito. Non hai oggetti per i quali confrontare. È come scrivere e x = dict(23\;dfg&^*$^%$^$%^)poi lamentarsi di come il confronto non funziona con il dizionario. Ovviamente non funzionerà. Il commento di Tim d'altra parte riguarda mutevole values, quindi perché ho detto che si tratta di questioni diverse.
AnnanFay,

1
@MikeyE: setrichiede che i valori siano eseguibili e dictche le chiavi siano eseguibili. set(x.keys())funzionerà sempre perché le chiavi devono essere hash, ma set(x.values())falliranno sui valori che non sono hash.
Tim Tisdall,

173

Quello che vuoi fare è semplicemente x==y

Quello che fai non è una buona idea, perché gli elementi di un dizionario non dovrebbero avere alcun ordine. Potresti confrontare [('a',1),('b',1)]con [('b',1), ('a',1)](stessi dizionari, ordine diverso).

Ad esempio, vedi questo:

>>> x = dict(a=2, b=2,c=3, d=4)
>>> x
{'a': 2, 'c': 3, 'b': 2, 'd': 4}
>>> y = dict(b=2,c=3, d=4)
>>> y
{'c': 3, 'b': 2, 'd': 4}
>>> zip(x.iteritems(), y.iteritems())
[(('a', 2), ('c', 3)), (('c', 3), ('b', 2)), (('b', 2), ('d', 4))]

La differenza è solo un elemento, ma l'algoritmo vedrà che tutti gli elementi sono diversi


@ THC4k, scusami per non averlo menzionato. Ma devo controllare quanti valori corrispondono in entrambi i dizionari.
user225312

Ok, quindi in base al mio aggiornamento, il mio modo di fare è ancora errato?
user225312

@AA: Ho aggiunto perché il tuo non funziona quando vuoi contare.
Jochen Ritzel,

Vedo, ma nel mio caso entrambi i dizionari sono della stessa lunghezza. E lo saranno sempre, perché è così che funziona il programma.
user225312

5
A partire da Python 3.6, dict è ordinato e pronto all'uso.
Phil

163
def dict_compare(d1, d2):
    d1_keys = set(d1.keys())
    d2_keys = set(d2.keys())
    shared_keys = d1_keys.intersection(d2_keys)
    added = d1_keys - d2_keys
    removed = d2_keys - d1_keys
    modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]}
    same = set(o for o in shared_keys if d1[o] == d2[o])
    return added, removed, modified, same

x = dict(a=1, b=2)
y = dict(a=2, b=2)
added, removed, modified, same = dict_compare(x, y)

7
Questo in realtà gestisce valori mutabili nel dict!
Tim Tisdall,

1
Quando eseguo questo, ricevo ancora un errore nel vedere i valori mutabili: ValueError: il valore di verità di un DataFrame è ambiguo. Usa a.empty, a.bool (), a.item (), a.any () o a.all ().
Afflatus,

2
@Afflatus - DataFrames in base alla progettazione non consentono confronti veritieri (a meno che non abbia una lunghezza di 1) come ereditano numpy.ndarray. -Credit a stackoverflow.com/a/33307396/994076
Daniel Myers

Questa è una gemma assoluta.
pfabri,

125

dic1 == dic2

Dai documenti di Python :

Per illustrare, i seguenti esempi restituiscono tutti un dizionario uguale a {"one": 1, "two": 2, "three": 3}:

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True

Fornire argomenti di parole chiave come nel primo esempio funziona solo per chiavi che sono identificatori Python validi. Altrimenti, è possibile utilizzare qualsiasi chiave valida.

Valido per entrambi py2e py3.


3
Non sono d'accordo con @ ErkinAlpGüney. Potresti fornire una prova?
Qi Luo,

4
Non sono d'accordo con @ ErkinAlpGüney. La documentazione ufficiale mostra che == confronta effettivamente i dizionari per valore, non per indirizzo. docs.python.org/2/library/stdtypes.html#mapping-types-dict
Matthew Nakayama

3
Opere per Python
2.7.13

4
@ankostis:OrderedDict != dict
CONvid19

3
Potete per favore fornire un input in cui ciò non è vero?
CONvocato 19

55

Sono nuovo di Python ma ho finito per fare qualcosa di simile a @mouad

unmatched_item = set(dict_1.items()) ^ set(dict_2.items())
len(unmatched_item) # should be 0

L'operatore XOR ( ^) dovrebbe eliminare tutti gli elementi del dict quando sono uguali in entrambi i dadi.


28
Sfortunatamente questo non funziona se i valori nel dict sono mutabili (cioè non cancellabili). (Ex {'a':{'b':1}}TypeError: unhashable type: 'dict')
Tim Tisdall il

54

Dal momento che sembra che nessuno ne abbia parlato deepdiff, lo aggiungerò qui per completezza. Lo trovo molto conveniente per ottenere diff di oggetti (nidificati) in generale:

Installazione

pip install deepdiff

Codice di esempio

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    }
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(diff, indent=4))

Produzione

{
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

Nota sulla stampa graziosa del risultato per l'ispezione: il codice sopra riportato funziona se entrambi i dadi hanno le stesse chiavi di attributo (con valori di attributo possibilmente diversi come nell'esempio). Tuttavia, se un "extra"attributo è presente è una delle dicts, json.dumps()fallisce con

TypeError: Object of type PrettyOrderedSet is not JSON serializable

Soluzione: utilizzare diff.to_json()e json.loads()/ json.dumps()per stampare piuttosto:

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    },
    "extra": 3
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(json.loads(diff.to_json()), indent=4))  

Produzione:

{
    "dictionary_item_removed": [
        "root['extra']"
    ],
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

Alternativa: uso pprint, risulta in una formattazione diversa:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

Produzione:

{   'dictionary_item_removed': [root['extra']],
    'values_changed': {   "root['a']": {   'new_value': 2,
                                           'old_value': 1},
                          "root['nested']['b']": {   'new_value': 2,
                                                     'old_value': 1}}}

2
Interessante. Grazie per aver risposto. Utile per me almeno. Questa risposta richiede più voti.
Archit Kapoor

46

Usa solo:

assert cmp(dict1, dict2) == 0

6
Sembra che il compito non sia solo quello di verificare se il contenuto di entrambi è lo stesso, ma anche di fornire un resoconto delle differenze
Diego Tercero,

29
Credo che sia identico adict1 == dict2
Trey Hunner,

10
Per chiunque usi Python3.5, il cmpbuilt-in è stato rimosso (e dovrebbe essere trattato come rimosso prima . Un'alternativa che propongono: (a > b) - (a < b) == cmp(a, b)per un equivalente funzionale (o migliore __eq__e __hash__)
nerdwaller

3
@nerdwaller - i dicts non sono tipi ordinabili, quindi dict_a> dict_b solleverà un TypeError:unorderable types: dict() < dict()
Stefano

2
@Stefano: buona chiamata, il mio commento è stato più per il confronto generale in Python (non stavo prestando attenzione alla risposta effettiva, errore mio).
nerdwaller,

9

La risposta di @mouad è buona se si assume che entrambi i dizionari contengano solo valori semplici. Tuttavia, se hai dizionari che contengono dizionari, otterrai un'eccezione poiché i dizionari non sono cancellabili.

In cima alla mia testa, qualcosa del genere potrebbe funzionare:

def compare_dictionaries(dict1, dict2):
     if dict1 is None or dict2 is None:
        print('Nones')
        return False

     if (not isinstance(dict1, dict)) or (not isinstance(dict2, dict)):
        print('Not dict')
        return False

     shared_keys = set(dict1.keys()) & set(dict2.keys())

     if not ( len(shared_keys) == len(dict1.keys()) and len(shared_keys) == len(dict2.keys())):
        print('Not all keys are shared')
        return False


     dicts_are_equal = True
     for key in dict1.keys():
         if isinstance(dict1[key], dict) or isinstance(dict2[key], dict):
             dicts_are_equal = dicts_are_equal and compare_dictionaries(dict1[key], dict2[key])
         else:
             dicts_are_equal = dicts_are_equal and all(atleast_1d(dict1[key] == dict2[key]))

     return dicts_are_equal

Se usi not isinstance(dict1, dict)invece di type(dict1) is not dict, questo funzionerà su altre classi basate su dict. Also, instead of (dict1 [chiave] == dict2 [chiave]) , you can do tutto (atleast_1d (dict1 [chiave] == dict2 [chiave])) `per gestire almeno le matrici.
EL_DON,

+1, ma potresti uscire dal tuo for loopnon appena dicts_are_equaldiventa falso. Non è necessario continuare oltre.
pfabri,

6

Ancora un'altra possibilità, fino all'ultima nota del PO, è di confrontare gli hash ( SHAo MD) dei dadi scaricati come JSON. Il modo in cui gli hash sono costruiti garantiscono che se sono uguali, anche le stringhe di origine sono uguali. Questo è molto veloce e matematicamente valido.

import json
import hashlib

def hash_dict(d):
    return hashlib.sha1(json.dumps(d, sort_keys=True)).hexdigest()

x = dict(a=1, b=2)
y = dict(a=2, b=2)
z = dict(a=1, b=2)

print(hash_dict(x) == hash_dict(y))
print(hash_dict(x) == hash_dict(z))

2
È completamente sbagliato, analizzare i dati in JSON è molto lento. Quindi eseguire l'hashing dell'enorme abbuffata che hai appena creato è anche peggio. Non dovresti mai farlo
Bruno,

7
@Bruno: citando l'OP: "Meglio non in velocità, sto parlando di eleganza del codice"
WoJ

2
Non è affatto elegante, sembra pericoloso ed è eccessivamente complicato per un problema davvero semplice
Bruno

7
@Bruno: l'eleganza è soggettiva. Posso capire che non ti piace (e probabilmente sottovalutato). Questo non è lo stesso di "sbagliato".
WoJ,

4
Questa è un'ottima risposta json.dumps(d, sort_keys=True)ti darà JSON canonico in modo che tu possa essere certo che entrambi i dict sono equivalenti. Inoltre dipende da cosa stai cercando di raggiungere. Non appena il valore non è serializzabile JSON, il valore fallirà. Per così chi dice che è inefficiente, dai un'occhiata al progetto UJSON.
Natim

6

La funzione è ottima IMO, chiara e intuitiva. Ma solo per darti (un'altra) risposta, ecco il mio go:

def compare_dict(dict1, dict2):
    for x1 in dict1.keys():
        z = dict1.get(x1) == dict2.get(x1)
        if not z:
            print('key', x1)
            print('value A', dict1.get(x1), '\nvalue B', dict2.get(x1))
            print('-----\n')

Può essere utile per te o per chiunque altro ..

MODIFICARE:

Ho creato una versione ricorsiva di quella sopra. Non l'ho vista nelle altre risposte

def compare_dict(a, b):
    # Compared two dictionaries..
    # Posts things that are not equal..
    res_compare = []
    for k in set(list(a.keys()) + list(b.keys())):
        if isinstance(a[k], dict):
            z0 = compare_dict(a[k], b[k])
        else:
            z0 = a[k] == b[k]

        z0_bool = np.all(z0)
        res_compare.append(z0_bool)
        if not z0_bool:
            print(k, a[k], b[k])
    return np.all(res_compare)

2
Miglioriamolo in modo che funzioni in entrambi i modi. Riga 2: "per x1 nel set (dict1.keys ()). Union (dict2.keys ()):"
nkadwa

Grazie @nkadwa, lo fa ora
zwep

5

Per verificare se due dadi sono uguali in chiavi e valori:

def dicts_equal(d1,d2):
    """ return True if all keys and values are the same """
    return all(k in d2 and d1[k] == d2[k]
               for k in d1) \
        and all(k in d1 and d1[k] == d2[k]
               for k in d2)

Se si desidera restituire valori diversi, scriverlo in modo diverso:

def dict1_minus_d2(d1, d2):
    """ return the subset of d1 where the keys don't exist in d2 or
        the values in d2 are different, as a dict """
    return {k,v for k,v in d1.items() if k in d2 and v == d2[k]}

Dovresti chiamarlo due volte, ad es

dict1_minus_d2(d1,d2).extend(dict1_minus_d2(d2,d1))

3

Codice

def equal(a, b):
    type_a = type(a)
    type_b = type(b)
    
    if type_a != type_b:
        return False
    
    if isinstance(a, dict):
        if len(a) != len(b):
            return False
        for key in a:
            if key not in b:
                return False
            if not equal(a[key], b[key]):
                return False
        return True

    elif isinstance(a, list):
        if len(a) != len(b):
            return False
        while len(a):
            x = a.pop()
            index = indexof(x, b)
            if index == -1:
                return False
            del b[index]
        return True
        
    else:
        return a == b

def indexof(x, a):
    for i in range(len(a)):
        if equal(x, a[i]):
            return i
    return -1

Test

>>> a = {
    'number': 1,
    'list': ['one', 'two']
}
>>> b = {
    'list': ['two', 'one'],
    'number': 1
}
>>> equal(a, b)
True

3

Un semplice confronto con == dovrebbe essere sufficiente al giorno d'oggi (python 3.8). Anche quando si confrontano gli stessi dadi in un ordine diverso (ultimo esempio). La cosa migliore è che non è necessario un pacchetto di terze parti per raggiungere questo obiettivo.

a = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
b = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}

c = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}
d = {'one': 'dog', 'two': 'cat', 'three': 'mouse', 'four': 'fish'}

e = {'one': 'cat', 'two': 'dog', 'three': 'mouse'}
f = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}

g = {'two': 'cat', 'one': 'dog', 'three': 'mouse'}
h = {'one': 'dog', 'two': 'cat', 'three': 'mouse'}


print(a == b) # True
print(c == d) # False
print(e == f) # False
print(g == h) # True

2

Essere in ritardo nella mia risposta è meglio che mai!

Confronta Not_Equal è più efficiente del confronto di Equal. In quanto tali due dicts non sono uguali se non si trovano valori chiave in un dict nell'altro dict. Il codice seguente tiene conto del fatto che potresti confrontare dict predefinito e quindi utilizza get anziché getitem [].

Utilizzando una sorta di valore casuale come predefinito nella chiamata get uguale alla chiave che viene recuperata - nel caso in cui i dicts abbiano un valore None come in un dict e quel tasto non esiste nell'altro. Inoltre, la condizione get! = Viene verificata prima della condizione non in efficienza perché si sta eseguendo il controllo su chiavi e valori da entrambi i lati contemporaneamente.

def Dicts_Not_Equal(first,second):
    """ return True if both do not have same length or if any keys and values are not the same """
    if len(first) == len(second): 
        for k in first:
            if first.get(k) != second.get(k,k) or k not in second: return (True)
        for k in second:         
            if first.get(k,k) != second.get(k) or k not in first: return (True)
        return (False)   
    return (True)

2

Sto usando questa soluzione che funziona perfettamente per me in Python 3


import logging
log = logging.getLogger(__name__)

...

    def deep_compare(self,left, right, level=0):
        if type(left) != type(right):
            log.info("Exit 1 - Different types")
            return False

        elif type(left) is dict:
            # Dict comparison
            for key in left:
                if key not in right:
                    log.info("Exit 2 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[str(key)], right[str(key)], level +1 ):
                        log.info("Exit 3 - different children")
                        return False
            return True
        elif type(left) is list:
            # List comparison
            for key in left:
                if key not in right:
                    log.info("Exit 4 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[left.index(key)], right[right.index(key)], level +1 ):
                        log.info("Exit 5 - different children")
                        return False
            return True
        else:
            # Other comparison
            return left == right

        return False

Confronta dict, list e altri tipi che implementano l'operatore "==" da soli. Se devi confrontare qualcos'altro di diverso, devi aggiungere un nuovo ramo nel "se albero".

Spero che aiuti.


2

per python3:

data_set_a = dict_a.items()
data_set_b = dict_b.items()

difference_set = data_set_a ^ data_set_b

1
>>> hash_1
{'a': 'foo', 'b': 'bar'}
>>> hash_2
{'a': 'foo', 'b': 'bar'}
>>> set_1 = set (hash_1.iteritems())
>>> set_1
set([('a', 'foo'), ('b', 'bar')])
>>> set_2 = set (hash_2.iteritems())
>>> set_2
set([('a', 'foo'), ('b', 'bar')])
>>> len (set_1.difference(set_2))
0
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...    print "The two hashes match."
...
The two hashes match.
>>> hash_2['c'] = 'baz'
>>> hash_2
{'a': 'foo', 'c': 'baz', 'b': 'bar'}
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...     print "The two hashes match."
...
>>>
>>> hash_2.pop('c')
'baz'

Ecco un'altra opzione:

>>> id(hash_1)
140640738806240
>>> id(hash_2)
140640738994848

Quindi, come vedi, i due ID sono diversi. Ma i ricchi operatori di confronto sembrano fare il trucco:

>>> hash_1 == hash_2
True
>>>
>>> hash_2
{'a': 'foo', 'b': 'bar'}
>>> set_2 = set (hash_2.iteritems())
>>> if (len(set_1.difference(set_2)) | len(set_2.difference(set_1))) == False:
...     print "The two hashes match."
...
The two hashes match.
>>>

1

In PyUnit c'è un metodo che confronta magnificamente i dizionari. L'ho provato usando i seguenti due dizionari e fa esattamente quello che stai cercando.

d1 = {1: "value1",
      2: [{"subKey1":"subValue1",
           "subKey2":"subValue2"}]}
d2 = {1: "value1",
      2: [{"subKey2":"subValue2",
           "subKey1": "subValue1"}]
      }


def assertDictEqual(self, d1, d2, msg=None):
        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')

        if d1 != d2:
            standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
            diff = ('\n' + '\n'.join(difflib.ndiff(
                           pprint.pformat(d1).splitlines(),
                           pprint.pformat(d2).splitlines())))
            standardMsg = self._truncateMessage(standardMsg, diff)
            self.fail(self._formatMessage(msg, standardMsg))

Non sto raccomandando l'importazione unittestnel tuo codice di produzione. Il mio pensiero è che la fonte in PyUnit potrebbe essere rielaborata per essere eseguita in produzione. Usa pprintquale "stampa carina" i dizionari. Sembra abbastanza facile adattare questo codice per essere "pronto per la produzione".


1

vedere gli oggetti di visualizzazione del dizionario: https://docs.python.org/2/library/stdtypes.html#dict

In questo modo è possibile sottrarre dictView2 da dictView1 e restituirà un insieme di coppie chiave / valore diverse in dictView2:

original = {'one':1,'two':2,'ACTION':'ADD'}
originalView=original.viewitems()
updatedDict = {'one':1,'two':2,'ACTION':'REPLACE'}
updatedDictView=updatedDict.viewitems()
delta=original | updatedDict
print delta
>>set([('ACTION', 'REPLACE')])

È possibile intersecare, unire, differenza (mostrato sopra), differenza simmetrica questi oggetti vista dizionario.
Meglio? Più veloce? - non sono sicuro, ma fa parte della libreria standard - il che lo rende un grande vantaggio per la portabilità


1

Di seguito il codice ti aiuterà a confrontare l'elenco di dict in Python

def compate_generic_types(object1, object2):
    if isinstance(object1, str) and isinstance(object2, str):
        return object1 == object2
    elif isinstance(object1, unicode) and isinstance(object2, unicode):
        return object1 == object2
    elif isinstance(object1, bool) and isinstance(object2, bool):
        return object1 == object2
    elif isinstance(object1, int) and isinstance(object2, int):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, float):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, int):
        return object1 == float(object2)
    elif isinstance(object1, int) and isinstance(object2, float):
        return float(object1) == object2

    return True

def deep_list_compare(object1, object2):
    retval = True
    count = len(object1)
    object1 = sorted(object1)
    object2 = sorted(object2)
    for x in range(count):
        if isinstance(object1[x], dict) and isinstance(object2[x], dict):
            retval = deep_dict_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        elif isinstance(object1[x], list) and isinstance(object2[x], list):
            retval = deep_list_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        else:
            retval = compate_generic_types(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False

    return retval

def deep_dict_compare(object1, object2):
    retval = True

    if len(object1) != len(object2):
        return False

    for k in object1.iterkeys():
        obj1 = object1[k]
        obj2 = object2[k]
        if isinstance(obj1, list) and isinstance(obj2, list):
            retval = deep_list_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

        elif isinstance(obj1, dict) and isinstance(obj2, dict):
            retval = deep_dict_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False
        else:
            retval = compate_generic_types(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

    return retval

3
Benvenuto in Stack Overflow! Sebbene questo frammento di codice possa risolvere la domanda, inclusa una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e quelle persone potrebbero non conoscere i motivi del tuo suggerimento sul codice. Cerca inoltre di non aggiungere il tuo codice a commenti esplicativi, ciò riduce la leggibilità sia del codice che delle spiegazioni!
Filnor,

1
>>> x = {'a':1,'b':2,'c':3}
>>> x
{'a': 1, 'b': 2, 'c': 3}

>>> y = {'a':2,'b':4,'c':3}
>>> y
{'a': 2, 'b': 4, 'c': 3}

METHOD 1:

>>> common_item = x.items()&y.items() #using union,x.item() 
>>> common_item
{('c', 3)}

METHOD 2:

 >>> for i in x.items():
        if i in y.items():
           print('true')
        else:
           print('false')


false
false
true

0

In Python 3.6, può essere fatto come: -

if (len(dict_1)==len(dict_2): 
  for i in dict_1.items():
        ret=bool(i in dict_2.items())

La variabile ret sarà vera se tutti gli elementi di dict_1 presenti in dict_2


0

Ecco la mia risposta, usa un modo ricorsivo:

def dict_equals(da, db):
    if not isinstance(da, dict) or not isinstance(db, dict):
        return False
    if len(da) != len(db):
        return False
    for da_key in da:
        if da_key not in db:
            return False
        if not isinstance(db[da_key], type(da[da_key])):
            return False
        if isinstance(da[da_key], dict):
            res = dict_equals(da[da_key], db[da_key])
            if res is False:
                return False
        elif da[da_key] != db[da_key]:
            return False
    return True

a = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
b = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
print dict_equals(a, b)

Spero che aiuti!


0

Perché non scorrere semplicemente un dizionario e controllare l'altro nel processo (supponendo che entrambi i dizionari abbiano le stesse chiavi)?

x = dict(a=1, b=2)
y = dict(a=2, b=2)

for key, val in x.items():
    if val == y[key]:
        print ('Ok', val, y[key])
    else:
        print ('Not', val, y[key])

Produzione:

Not 1 2
Ok 2 2

0

Il modo più semplice (e uno dei più robusti) di fare un confronto profondo tra due dizionari è serializzarli in formato JSON, ordinare le chiavi e confrontare i risultati delle stringhe:

import json
if json.dumps(x, sort_keys=True) == json.dumps(y, sort_keys=True):
   ... Do something ...

-7
import json

if json.dumps(dict1) == json.dumps(dict2):
    print("Equal")

1
Questo potrebbe non fare esattamente ciò che è stato richiesto e inserire la json std lib, ma funziona (come json.dumpsè deterministico con le impostazioni predefinite).
Daniel Farrell,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.