Comparando dois dicionários e verificando quantos pares (chave, valor) são iguais

246

Eu tenho dois dicionários, mas, para simplificação, vou usar estes dois:

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

Agora, quero comparar se cada key, valuepar xtem o mesmo valor correspondente em y. Então eu escrevi isso:

>>> 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 funciona desde que a tupleé retornado e depois comparado para igualdade.

Minhas perguntas:

Isso está correto? Existe uma maneira melhor de fazer isso? Melhor não em velocidade, estou falando sobre elegância de código.

UPDATE: Esqueci de mencionar que tenho que verificar quantos key, valuepares são iguais.

user225312
fonte
21
x == ydeve ser verdade de acordo com stackoverflow.com/a/5635309/186202
Natim
x == y deve ser verdadeiro. Pode-se verificar rapidamente no REPL. Consulte: docs.python.org/2/library/stdtypes.html#mapping-types-dict
Vikrant

Respostas:

179

Se você quiser saber quantos valores correspondem nos dois dicionários, deveria ter dito isso :)

Talvez algo parecido com isto:

shared_items = {k: x[k] for k in x if k in y and x[k] == y[k]}
print len(shared_items)
mouad
fonte
1
Mesmo erro se houver um elemento de lista para a chave dict. Acho que o cmp é a melhor maneira de fazer isso, a menos que eu esteja perdendo alguma coisa.
Mutant
@ Mutante que é uma questão diferente. Você não pode criar um dicionário com uma listchave em primeiro lugar. x = {[1,2]: 2}vai falhar. A pergunta já tem validade dicts.
AnnanFay
@annan: errado, a questão é genérica. o exemplo na descrição da pergunta já tem "dados válidos". Se eu postar uma nova pergunta, com o mesmo título, mas com um ditado "inválido" diferente, alguém a marcará como duplicada. Downvoting.
Ribamar # 11/16
6
@ribamar a pergunta é "Comparando dois dicionários [...]". O 'dict inválido' acima com listchaves não é um código python válido - as chaves do dict devem ser imutáveis. Portanto, você não está comparando dicionários. Se você tentar usar uma lista como uma chave de dicionário, seu código não será executado. Você não tem objetos para os quais comparar. É como digitar x = dict(23\;dfg&^*$^%$^$%^)e reclamar como a comparação não funciona com o dicionário. Claro que não vai funcionar. O comentário de Tim, por outro lado, é sobre mutável values, por isso eu disse que essas são questões diferentes.
AnnanFay
1
@MikeyE - setexige que os valores sejam laváveis ​​e dictque as chaves sejam laváveis. set(x.keys())sempre funcionará porque as chaves precisam ser laváveis, mas set(x.values())falharão em valores que não são laváveis.
precisa
173

O que você quer fazer é simplesmente x==y

O que você faz não é uma boa ideia, porque os itens de um dicionário não devem ter nenhum pedido. Você pode estar comparando [('a',1),('b',1)]com [('b',1), ('a',1)](mesmos dicionários, ordem diferente).

Por exemplo, veja isto:

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

A diferença é de apenas um item, mas seu algoritmo verá que todos os itens são diferentes

Jochen Ritzel
fonte
@ THC4k, desculpe por não mencionar. Mas tenho que verificar quantos valores correspondem nos dois dicionários.
user225312
Ok, então, com base na minha atualização, minha maneira de fazer ainda está incorreta?
user225312
@AA: eu adicionei porque o seu não funciona quando você quer contar.
Jochen Ritzel
Entendo, mas no meu caso os dois dicionários têm o mesmo comprimento. E sempre serão, porque é assim que o programa funciona.
user225312
5
A partir do Python 3.6, o dict é solicitado imediatamente.
31418 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)
Daniel Myers
fonte
7
Este realmente lida com valores mutáveis ​​no dict!
21415 Timothy Tisdall
1
Quando executo isso, ainda recebo um erro ao lidar com os valores mutáveis: ValueError: o valor verdadeiro de um DataFrame é ambíguo. Use a.empty, a.bool (), a.item (), a.any () ou a.all ().
Afflatus
2
@Afflatus - DataFrames por design não permite comparações verdadeiras (a menos que tenha um comprimento de 1), pois elas são herdadas numpy.ndarray. -credit para stackoverflow.com/a/33307396/994076
Daniel Myers
Esta é uma jóia absoluta.
pfabri 27/05
125

dic1 == dic2

Dos documentos python :

Para ilustrar, todos os exemplos a seguir retornam um dicionário igual 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

O fornecimento de argumentos de palavras-chave, como no primeiro exemplo, funciona apenas para chaves que são identificadores Python válidos. Caso contrário, qualquer chave válida pode ser usada.

Válido para ambos py2e py3.

CONvid19
fonte
3
Não concordo com @ ErkinAlpGüney. Você poderia fornecer uma prova?
Qi Luo
4
Não concordo com @ ErkinAlpGüney. A documentação oficial mostra que == realmente compara dicionários por valor, não por endereço. docs.python.org/2/library/stdtypes.html#mapping-types-dict
Matthew Nakayama
3
Funciona para Python 2.7.13
Jesuisme
4
@ankostis:OrderedDict != dict
CONvid19 /
3
Você pode fornecer uma entrada onde isso não é verdade?
CONvid19
55

Eu sou novo em python, mas acabei fazendo algo semelhante ao @mouad

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

O operador XOR ( ^) deve eliminar todos os elementos do ditado quando forem iguais nos dois ditados.

philipp
fonte
28
Infelizmente, isso não funciona se os valores no dict são mutáveis ​​(ou seja, não podem ser lavados). (Ex {'a':{'b':1}}TypeError: unhashable type: 'dict')
Tim Tisdall
54

Como parece que ninguém mencionou deepdiff, vou adicioná-lo aqui para completar. Eu acho muito conveniente para obter diff de objetos (aninhados) em geral:

Instalação

pip install deepdiff

Código de amostra

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

Resultado

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

Nota sobre a impressão bonita do resultado para inspeção: O código acima funciona se ambos os dictos tiverem as mesmas chaves de atributo (com valores de atributo possivelmente diferentes, como no exemplo). No entanto, se um "extra"atributo estiver presente é um dos dictos, json.dumps()falhará com

TypeError: Object of type PrettyOrderedSet is not JSON serializable

Solução: use diff.to_json()e json.loads()/ json.dumps()para imprimir bem:

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

Resultado:

{
    "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: use pprint, resulta em uma formatação diferente:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

Resultado:

{   'dictionary_item_removed': [root['extra']],
    'values_changed': {   "root['a']": {   'new_value': 2,
                                           'old_value': 1},
                          "root['nested']['b']": {   'new_value': 2,
                                                     'old_value': 1}}}
Sumudu
fonte
2
Interessante. Obrigado por responder. Útil para mim pelo menos. Esta resposta precisa de mais votos.
Archit Kapoor
46

Apenas use:

assert cmp(dict1, dict2) == 0
Shiyu
fonte
6
Parece que a tarefa não é apenas para verificar se o conteúdo de ambos são os mesmos, mas também para dar um relatório das diferenças
Diego Tercero
29
Eu acredito que isso é idêntico adict1 == dict2
Trey Hunner
10
Para qualquer pessoa que utilize Python3.5, o cmpconstruído em foi removida (e devem ser tratados como removido antes Uma alternativa eles propõem:. (a > b) - (a < b) == cmp(a, b)Por um seu equivalente funcional (ou melhor __eq__e __hash__)
nerdwaller
3
@nerdwaller - dict não são tipos ordenáveis, então dict_a> dict_b geraria um TypeError::unorderable types: dict() < dict()
Stefano
2
@ Stefano: Boa ligação, meu comentário foi mais para comparação geral em python (eu não estava prestando atenção à resposta real, meu erro).
Nerdwaller 11/10
9

A resposta de @mouad é boa se você assumir que ambos os dicionários contêm apenas valores simples. No entanto, se você tiver dicionários que contenham dicionários, você receberá uma exceção, pois os dicionários não são hasháveis.

Em cima da minha cabeça, algo como isto pode funcionar:

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
Alexander
fonte
Se você usar em not isinstance(dict1, dict)vez de type(dict1) is not dict, isso funcionará em outras classes baseadas em dict. Also, instead of (dict1 [chave] == dict2 [chave]) , you can do todas (atleast_1d (dict1 [chave] == dict2 [chave])) `para manipular matrizes pelo menos.
EL_DON 22/03/19
+1, mas você pode sair do seu for loopassim que dicts_are_equalse tornar falso. Não há necessidade de continuar mais.
pfabri 27/05
6

Outra possibilidade, até a última nota do OP, é comparar os hashes ( SHAou MD) dos dictos despejados como JSON. A maneira como os hashes são construídos garante que, se forem iguais, as cadeias de origem também sejam iguais. Isso é muito rápido e matematicamente correto.

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))
WoJ
fonte
2
Isso está completamente errado, apenas analisar os dados no json é muito lento. Então hashing esse enorme sring que você acabou de criar é ainda pior. Você nunca deve fazer isso
de Bruno
7
@Bruno: citando o OP: "Melhor não na velocidade, eu estou falando sobre a elegância de código"
woj
2
Não é elegante em tudo, ele se sente inseguro e é muito complicada para um problema muito simples
de Bruno
7
@ Bruno: a elegância é subjetiva. Eu posso entender que você não gosta (e provavelmente com voto negativo). Isso não é o mesmo que "errado".
WoJ
4
Esta é uma ótima resposta. json.dumps(d, sort_keys=True)fornecerá JSON canônico para que você possa ter certeza de que os dois dict são equivalentes. Também depende do que você está tentando obter. Assim que o valor não for JSON serizalizable, ele falhará. Para quem diz que é ineficiente, dê uma olhada no projeto ujson.
Natim
6

A função é fina IMO, clara e intuitiva. Mas apenas para lhe dar (outra) resposta, aqui está a minha chance:

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

Pode ser útil para você ou para qualquer outra pessoa.

EDITAR:

Eu criei uma versão recursiva da acima. Não vi isso nas outras respostas

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)
zwep
fonte
2
Vamos melhorá-lo para que funcione nos dois sentidos. Linha 2: "para x1 no conjunto (dict1.keys ()). Union (dict2.keys ()):"
nkadwa
Graças @nkadwa, faz agora
zwep
5

Para testar se dois ditados são iguais em chaves e valores:

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 você deseja retornar os valores que diferem, escreva-o de forma diferente:

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

Você teria que chamá-lo duas vezes, ou seja

dict1_minus_d2(d1,d2).extend(dict1_minus_d2(d2,d1))
simonltwick
fonte
3

Código

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

Teste

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

Uma simples comparação com == deve ser suficiente atualmente (python 3.8). Mesmo quando você compara os mesmos ditados em uma ordem diferente (último exemplo). O melhor é que você não precisa de um pacote de terceiros para fazer isso.

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
Nebulostic
fonte
2

Chegar atrasado na minha resposta é melhor do que nunca!

Comparar Not_Equal é mais eficiente do que comparar Igual. Como tais dois ditados não são iguais se nenhum valor-chave em um ditado não for encontrado no outro ditado. O código abaixo leva em consideração que você talvez esteja comparando o dict padrão e, portanto, usa get em vez de getitem [].

Usar um tipo de valor aleatório como padrão na chamada get igual à chave que está sendo recuperada - apenas no caso de os dictos terem um None como valor em um dict e essa chave não existir no outro. Além disso, a condição get! = É verificada antes da condição não em termos de eficiência, porque você está verificando as chaves e os valores de ambos os lados ao mesmo tempo.

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)
user-asterix
fonte
2

Estou usando esta solução que funciona perfeitamente para mim no 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

Ele compara dict, list e quaisquer outros tipos que implementem o operador "==" sozinhos. Se você precisar comparar algo diferente, adicione um novo ramo na "se árvore".

Espero que ajude.

Giovanni Basolu
fonte
2

para python3:

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

difference_set = data_set_a ^ data_set_b
Bryant
fonte
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'

Aqui está outra opção:

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

Então, como você vê, os dois IDs são diferentes. Mas os ricos operadores de comparação parecem fazer o truque:

>>> 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.
>>>
LED Zeppelin
fonte
1

No PyUnit, existe um método que compara dicionários lindamente. Testei-o usando os dois dicionários a seguir e ele faz exatamente o que você está procurando.

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

Não recomendo importar unittestpara o seu código de produção. Meu pensamento é que a fonte no PyUnit poderia ser reutilizada para executar na produção. Ele usa pprint"impressões bonitas" nos dicionários. Parece muito fácil adaptar esse código para estar "pronto para produção".

MikeyE
fonte
1

consulte o dicionário para ver objetos: https://docs.python.org/2/library/stdtypes.html#dict

Dessa forma, você pode subtrair o dictView2 do dictView1 e ele retornará um conjunto de pares de chave / valor diferentes no 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')])

Você pode interceptar, união, diferença (mostrada acima), diferença simétrica esses objetos de exibição de dicionário.
Melhor? Mais rápido? - não tenho certeza, mas parte da biblioteca padrão - o que torna uma grande vantagem para a portabilidade

tranimatronic
fonte
1

O código abaixo o ajudará a comparar a lista de dict em 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
Vitthal Kadam
fonte
3
Bem-vindo ao Stack Overflow! Embora esse trecho de código possa resolver a questão, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código. Tente também não sobrecarregar seu código com comentários explicativos, pois isso reduz a legibilidade do código e das explicações!
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
vidiv
fonte
0

No Python 3.6, isso pode ser feito como: -

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

A variável ret será verdadeira se todos os itens de dict_1 presentes no dict_2

Souravi Sinha
fonte
0

Aqui está a minha resposta, use uma maneira recursize:

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)

Espero que ajude!

William Xu
fonte
0

Por que não apenas percorrer um dicionário e verificar o outro no processo (assumindo que os dois dicionários tenham as mesmas chaves)?

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

Resultado:

Not 1 2
Ok 2 2
LevB
fonte
-7
import json

if json.dumps(dict1) == json.dumps(dict2):
    print("Equal")
Mariusz K
fonte
1
Isso pode não fazer exatamente o que foi solicitado e extrai o json std lib, mas funciona (como json.dumpsé determinístico nas configurações padrão).
22416 Daniel Farrell #