Suponha que eu tenha dois dicionários Python - dictA
e dictB
. Preciso descobrir se existem chaves presentes ou dictB
não dictA
. Qual é a maneira mais rápida de fazer isso?
Devo converter as chaves do dicionário em um conjunto e depois continuar?
Interessado em conhecer seus pensamentos ...
Obrigado por suas respostas.
Desculpas por não ter feito a pergunta corretamente. Meu cenário é o seguinte: eu tenho um dictA
que pode ser o mesmo dictB
ou pode ter algumas chaves ausentes em comparação com dictB
ou o valor de algumas chaves pode ser diferente, o que deve ser definido como dictA
o valor da chave.
O problema é que o dicionário não tem padrão e pode ter valores que podem ser dict of dict.
Dizer
dictA={'key1':a, 'key2':b, 'key3':{'key11':cc, 'key12':dd}, 'key4':{'key111':{....}}}
dictB={'key1':a, 'key2:':newb, 'key3':{'key11':cc, 'key12':newdd, 'key13':ee}.......
Portanto, o valor 'key2' deve ser redefinido para o novo valor e 'key13' deve ser adicionado dentro do dict. O valor da chave não possui um formato fixo. Pode ser um valor simples ou um ditado ou ditado.
fonte
def update(self, new_dict): self.__init__(new_dict, self.current_dict)
ou similar para que você possa fazer uma comparação rolandoDictDiffer
classe é uma classe sem estado e pode ser uma função. Os valoreschanged
eunchanged
podem ser calculados no mesmo loop. Essas duas funções podem retornar um emlist
vez de umset
que certamente é menos caro. Para uma comparação profunda, você pode dar uma olhada na estrutura de teste da unidade: docs.python.org/2/library/unittest.html , basta seguir oassertDictEqual
método no código-fonte.set(dictb)
provavelmente é melhor queset(dictb.keys())
.Caso você queira a diferença recursivamente, escrevi um pacote para python: https://github.com/seperman/deepdiff
Instalação
Instale a partir do PyPi:
Exemplo de uso
Importação
O mesmo objeto retorna vazio
O tipo de um item foi alterado
O valor de um item foi alterado
Item adicionado e / ou removido
Diferença de cadeia
Diferença de string 2
Alteração de tipo
Diferença de lista
Diferença de lista 2:
Listar a diferença de ordem de ignição ou duplicatas: (com os mesmos dicionários acima)
Lista que contém o dicionário:
Conjuntos:
Tuplas nomeadas:
Objetos personalizados:
Atributo de objeto adicionado:
fonte
ignore_order=True
. Você pode encontrar os documentos em deepdiff.readthedocs.io/en/latest/diff.htmlnão tenho certeza se é "rápido" ou não, mas normalmente, pode-se fazer isso
fonte
dicta
edictb
já que ele quer saber essas chavesdictb
não estãodicta
.for key in dicta.keys():
=>for key in dicta:
Como escreveu Alex Martelli, se você simplesmente deseja verificar se alguma chave em B não está em A,
any(True for k in dictB if k not in dictA)
seria o caminho a seguir.Para encontrar as chaves que estão faltando:
Portanto, essas duas soluções têm praticamente a mesma velocidade.
fonte
any(k not in dictA for k in dictB)
Se você realmente quer dizer exatamente o que diz (que você só precisa descobrir se "existem chaves" em B e não em A, e NÃO QUAIS SÃO, se houver), o caminho mais rápido deve ser:
Se você realmente precisa descobrir QUAIS CHAVES, se houver alguma, estão em B e não em A, e não apenas "SE" existem essas chaves, as respostas existentes são bastante apropriadas (mas sugiro mais precisão em perguntas futuras, se for o caso). na verdade o que você quer dizer ;-).
fonte
Use
set()
:fonte
set(d)
já retorna apenas as teclas, para que você possa fazerset(da).intersection(db)
A resposta principal de hughdbrown sugere o uso de diferenças definidas, que é definitivamente a melhor abordagem:
O problema com esse código é que ele cria duas listas apenas para criar dois conjuntos, portanto, está perdendo tempo de 4N e espaço de 2N. Também é um pouco mais complicado do que precisa ser.
Normalmente, isso não é grande coisa, mas se for:
collections.abc.Mapping
possui umKeysView
que age como aSet
.Python 2
No Python 2,
keys()
retorna uma lista das chaves, não aKeysView
. Então você tem que pedirviewkeys()
diretamente.Para o código da versão dupla 2.7 / 3.x, espero que você esteja usando
six
ou algo semelhante, para poder usarsix.viewkeys(dictb)
:Em 2.4-2.6, não há
KeysView
. Mas você pode pelo menos reduzir o custo de 4N para N construindo seu conjunto esquerdo diretamente de um iterador, em vez de criar uma lista primeiro:Itens
Então você realmente não precisa comparar as chaves, mas os itens. An
ItemsView
é apenas aSet
se os valores forem hasháveis, como strings. Se forem, é fácil:Diferença recursiva
Embora a pergunta não esteja solicitando diretamente uma diferença recursiva, alguns dos valores de exemplo são dictos e parece que a saída esperada os diferencia recursivamente. Já existem várias respostas aqui mostrando como fazer isso.
fonte
Há uma outra questão no stackoverflow sobre esse argumento e devo admitir que há uma solução simples explicada: a biblioteca de datadiff do python ajuda a imprimir a diferença entre dois dicionários.
fonte
Aqui está uma maneira de funcionar, permitir que as chaves avaliem
False
e ainda use uma expressão geradora para sair mais cedo, se possível. Não é excepcionalmente bonito.EDITAR:
THC4k postou uma resposta ao meu comentário em outra resposta. Aqui está uma maneira melhor e mais bonita de fazer o acima:
Não sei como isso nunca passou pela minha cabeça ...
fonte
any(k for k in dictB if k not in dictA)
que não é a mesma coisa (para chaves falsey). Verifique o histórico de edição / registros de data e hora.Esta é uma pergunta antiga e faz um pouco menos do que eu precisava, então essa resposta realmente resolve mais do que essa pergunta. As respostas nesta pergunta me ajudaram a resolver o seguinte:
Tudo isso combinado com JSON contribui para um suporte de armazenamento de configuração bastante poderoso.
A solução ( também no github ):
fonte
e o standart (compare o objeto completo)
PyDev-> novo módulo PyDev-> Módulo: unittest
fonte
Se estiver em Python ≥ 2,7:
fonte
Aqui está uma solução para comparar profundamente duas chaves de dicionários:
fonte
aqui está uma solução que pode comparar mais de dois ditados:
exemplo de uso:
fonte
Minha receita de diferença simétrica entre dois dicionários:
E o resultado é:
fonte
Como mencionado em outras respostas, o unittest produz uma boa saída para comparar ditados, mas neste exemplo não queremos ter que construir um teste inteiro primeiro.
Rascunhando a fonte mais unida, parece que você pode obter uma solução justa com apenas isso:
tão
Resulta em:
Onde:
Como no mais unittest, a única ressalva é que o mapeamento final pode ser considerado um diff, devido à vírgula / colchete à direita.
fonte
O @Maxx tem uma excelente resposta, use as
unittest
ferramentas fornecidas pelo Python:Em qualquer lugar do seu código, você pode ligar para:
A saída resultante se parece com a saída
diff
, imprimindo os dicionários com+
ou-
acrescentando cada linha diferente.fonte
Não tenho certeza se ainda é relevante, mas me deparei com esse problema, minha situação só precisava retornar um dicionário das alterações para todos os dicionários aninhados, etc. Não foi possível encontrar uma boa solução por aí, mas acabei escrevendo uma função simples para fazer isso . Espero que isto ajude,
fonte
Se você deseja uma solução integrada para uma comparação completa com estruturas de dict arbitrárias, a resposta do @ Maxx é um bom começo.
fonte
Com base na resposta de ghostdog74,
imprimirá um valor diferente de dicta
fonte
Tente isso para encontrar a interseção, as chaves que estão nos dois dictionarie, se você quiser que as chaves não sejam encontradas no segundo dictionarie, basta usar o not in ...
fonte