Como mesclar dois dicionários em uma única expressão?

votos
3k

Eu tenho dois dicionários Python, e eu quero escrever uma única expressão que retorna esses dois dicionários, mescladas. O update()método seria o que eu preciso, se ele voltou seu resultado em vez de modificar um dicionário no local.

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}

Como posso obter esse dict mesclado final z, não x?

(Para ser extra-claro, o último-um-ganha conflito de manipulação de dict.update()é o que eu estou procurando também.)

Publicado 02/09/2008 em 08:44
fonte usuário
Em outras línguas...                            


49 respostas

votos
3k

Como posso mesclar dois dicionários Python em uma única expressão?

Para dicionários xe y, ztorna-se um dicionário mesclado com valores de ysubstituir os de x.

  • Em Python 3,5 ou maior,:

    z = {**x, **y}
    
  • Em Python 2, (ou 3,4 ou inferior) escrever uma função:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with x's keys and values
        z.update(y)    # modifies z with y's keys and values & returns None
        return z
    

    e

    z = merge_two_dicts(x, y)
    

Explicação

Digamos que você tenha duas dicts e você quer fundi-los em um novo dict sem alterar as dicts originais:

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

O resultado desejado é obter um novo dicionário ( z) com os valores fundiram, e os valores do segundo dict substituir os da primeira.

>>> z
{'a': 1, 'b': 3, 'c': 4}

Uma nova sintaxe para isso, proposto em PEP 448 e disponível a partir do Python 3.5 , é

z = {**x, **y}

E é de facto uma única expressão. Ele agora está mostrando como implementado no calendário de lançamentos para 3,5, PEP 478 , e já fez o seu caminho em que há de novo em Python 3.5 documento.

No entanto, uma vez que muitas organizações ainda estão em Python 2, você pode querer fazer isso de uma maneira compatível com versões anteriores. A maneira classicamente Pythonic, disponível em Python 2 e 3,0-3,4, é de fazer isto como um processo de dois passos:

z = x.copy()
z.update(y) # which returns None since it mutates z

Em ambas as abordagens, yvirá segunda e seus valores substituirão xos valores 's, assim, 'b'irá apontar para 3no nosso resultado final.

Ainda não em Python 3.5, mas quer um única expressão

Se você ainda não estão em Python 3.5, ou a necessidade de escrever código compatível com versões anteriores, e você quer isso em uma única expressão , o mais alto desempenho, enquanto abordagem correta é colocá-lo em uma função:

def merge_two_dicts(x, y):
    """Given two dicts, merge them into a new dict as a shallow copy."""
    z = x.copy()
    z.update(y)
    return z

e então você tem uma única expressão:

z = merge_two_dicts(x, y)

Você também pode fazer uma função para mesclar um número indefinido de dicts, de zero a um número muito grande:

def merge_dicts(*dict_args):
    """
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result

Esta função irá trabalhar em Python 2 e 3 para todos os dicts. por exemplo, dado dicts apara g:

z = merge_dicts(a, b, c, d, e, f, g) 

e pares de valores-chave no gterão precedência sobre dicts apara f, e assim por diante.

Críticas de outras respostas

Não use o que você vê na resposta anteriormente aceite:

z = dict(x.items() + y.items())

Em Python 2, você cria duas listas em memória para cada dict, criar uma terceira lista na memória com comprimento igual ao comprimento dos dois primeiros colocados juntos, e, em seguida, descartar todas as três listas para criar o dict. Em Python 3, este irá falhar porque você está adicionando dois dict_itemsobjetos juntos, não duas listas -

>>> c = dict(a.items() + b.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'dict_items' and 'dict_items'

e você teria que criá-los explicitamente como listas, por exemplo z = dict(list(x.items()) + list(y.items())). Este é um desperdício de recursos e poder de computação.

Da mesma forma, levando a união de items()em Python 3 ( viewitems()em Python 2.7) também falhará quando os valores são objetos unhashable (como listas, por exemplo). Mesmo que seus valores são Hashable, desde conjuntos são semanticamente não-ordenada, o comportamento é indefinido em relação à precedência. Portanto, não fazer isso:

>>> c = dict(a.items() | b.items())

Este exemplo demonstra o que acontece quando os valores são unhashable:

>>> x = {'a': []}
>>> y = {'b': []}
>>> dict(x.items() | y.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Aqui está um exemplo onde y deve ter precedência, mas em vez disso o valor de x é mantida devido à ordem arbitrária de conjuntos:

>>> x = {'a': 2}
>>> y = {'a': 1}
>>> dict(x.items() | y.items())
{'a': 2}

Outra cortar você não deve usar:

z = dict(x, **y)

Este usa o dictconstrutor, e é muito rápido e eficiente de memória (até mesmo um pouco mais-do que o nosso processo de duas etapas), mas se você não sabe exatamente o que está acontecendo aqui (isto é, o segundo dict está sendo passado como argumentos para o dict construtor), é difícil de ler, não é o uso pretendido, e por isso não é Pythonic.

Aqui está um exemplo do uso que está sendo corrigido no Django .

Dicts se destinam a ter chaves Hashable (por exemplo frozensets ou tuplos), mas este método não em Python 3 quando as chaves não são cadeias.

>>> c = dict(a, **b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

A partir da lista de discussão , Guido van Rossum, criador da linguagem, escreveu:

Eu estou bem com declarar dict ({}, ** {1: 3}) ilegal, já que afinal é o abuso do mecanismo **.

e

Aparentemente dict (x, y **) está acontecendo ao redor como "truque cool" para "chamada x.update (y) e retornar x". Pessoalmente acho que é mais desprezível do que legal.

É meu entendimento (bem como a compreensão do criador da linguagem ) que o uso pretendido para dict(**y)é para a criação de dicts para fins de legibilidade, por exemplo:

dict(a=1, b=10, c=11)

ao invés de

{'a': 1, 'b': 10, 'c': 11}

Resposta aos comentários

Apesar do que Guido diz, dict(x, **y)está em linha com a especificação dict, que btw. funciona tanto para Python 2 e 3. O fato de que isso só funciona para as chaves string é uma consequência direta de como parâmetros de palavra-chave funciona e não um curto-comming de dict. Nem está usando o operador ** neste lugar um abuso do mecanismo, de fato ** foi concebido precisamente para passar dicts como palavras-chave.

Novamente, ele não funciona para 3 quando as chaves são não-strings. O contrato de chamada implícita é que namespaces tomar dicts comuns, enquanto os usuários só devem passar argumentos-chave que são strings. Todas as outras funções chamáveis aplicadas lo. dictquebrou esta consistência em Python 2:

>>> foo(**{('a', 'b'): None})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() keywords must be strings
>>> dict(**{('a', 'b'): None})
{('a', 'b'): None}

Esta inconsistência foi ruim dado outras implementações de Python (PyPy, Jython, IronPython). Assim, foi fixado em Python 3, como esta utilização pode ser uma alteração de quebra.

Digo a vocês que é incompetência maliciosa para escrever intencionalmente código que só funciona em uma versão de uma língua ou que apenas obras dadas certas restrições arbitrárias.

Outro comentário:

dict(x.items() + y.items()) ainda é a solução mais legível para Python 2. contagens de legibilidade.

Minha resposta: merge_two_dicts(x, y)na verdade, parece muito mais claro para mim, se estamos realmente preocupados com a legibilidade. E não é para a frente compatível, como Python 2 está cada vez mais obsoleta.

Menos eficaz, mas correta Ad-HoCs

Estas abordagens são menos eficaz, mas eles irão fornecer o comportamento correto. Eles serão muito menos eficaz do que copye updateou o novo desembalar porque iterar cada par de valores-chave em um nível mais alto de abstração, mas eles fazer respeitar a ordem de precedência (últimos dicts têm precedência)

Você também pode encadear as dicts manualmente dentro de uma compreensão dict:

{k: v for d in dicts for k, v in d.items()} # iteritems in Python 2.7

ou em python 2.6 (e talvez já em 2.4, quando gerador de expressões foram introduzidas):

dict((k, v) for d in dicts for k, v in d.items())

itertools.chain vai acorrentar os iteradores sobre os pares chave-valor na ordem correta:

import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))

Análise de desempenho

Eu só vou fazer a análise dos usos conhecidos para se comportar corretamente desempenho.

import timeit

O seguinte é feito no Ubuntu 14.04

Em Python 2,7 (sistema Python):

>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.5726828575134277
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.163769006729126
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.iteritems(), y.iteritems()))))
1.1614501476287842
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
2.2345519065856934

Em Python 3,5 (deadsnakes PPA):

>>> min(timeit.repeat(lambda: {**x, **y}))
0.4094954460160807
>>> min(timeit.repeat(lambda: merge_two_dicts(x, y)))
0.7881555100320838
>>> min(timeit.repeat(lambda: {k: v for d in (x, y) for k, v in d.items()} ))
1.4525277839857154
>>> min(timeit.repeat(lambda: dict(itertools.chain(x.items(), y.items()))))
2.3143140770262107
>>> min(timeit.repeat(lambda: dict((k, v) for d in (x, y) for k, v in d.items())))
3.2069112799945287

Recursos sobre Dicionários

Respondeu 10/11/2014 em 22:11
fonte usuário

votos
1k

No seu caso, o que você pode fazer é:

z = dict(x.items() + y.items())

Esta vontade, como você quiser, colocar o dict final z, e fazer o valor para a chave bser devidamente substituído pelo segundo ( yvalor de dict):

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}

Se você usar o Python 3, é apenas um pouco mais complicado. Para criar z:

>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
Respondeu 02/09/2008 em 08:50
fonte usuário

votos
542

Uma alternativa:

z = x.copy()
z.update(y)
Respondeu 02/09/2008 em 14:00
fonte usuário

votos
269

Outra, mais conciso, opção:

z = dict(x, **y)

Nota : este tornou-se uma resposta popular, mas é importante ressaltar que, se ytem todas as chaves não-corda, o fato de que isso funciona em tudo é um abuso de detalhe de implementação CPython, e ele não funciona em Python 3, ou em PyPy, IronPython, ou Jython. Além disso, Guido não é um fã . Então, eu não posso recomendar esta técnica para o código portátil de implementação cruz frente-compatível ou, o que realmente significa que ele deve ser totalmente evitada.

Respondeu 02/09/2008 em 16:52
fonte usuário

votos
165

Este provavelmente não será uma resposta popular, mas você quase certamente não quero fazer isso. Se você quiser uma cópia que é uma junção, então usar cópia (ou deepcopy , dependendo do que você quiser) e depois atualizar. As duas linhas de código são muito mais legível - mais Pythonic - do que a criação de linha única com .items () + .items (). Explícito é melhor que implícito.

Além disso, quando você usa .items () (pré Python 3.0), você está criando uma nova lista que contém os itens do dict. Se os seus dicionários são grandes, então isso é bastante gerais (duas grandes listas que vai ser jogado fora assim que o dict mesclado é criado). update () pode funcionar de forma mais eficiente, porque ele pode ser executado através do segundo dict item por item.

Em termos de tempo :

>>> timeit.Timer("dict(x, **y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.52571702003479
>>> timeit.Timer("temp = x.copy()\ntemp.update(y)", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
15.694622993469238
>>> timeit.Timer("dict(x.items() + y.items())", "x = dict(zip(range(1000), range(1000)))\ny=dict(zip(range(1000,2000), range(1000,2000)))").timeit(100000)
41.484580039978027

IMO a pequena desaceleração entre os dois primeiros vale a pena para a legibilidade. Além disso, os argumentos de palavra-chave para a criação de dicionário só foi adicionada no Python 2.3, enquanto copiar () e update () irá funcionar em versões mais antigas.

Respondeu 08/09/2008 em 12:16
fonte usuário

votos
114

Em uma resposta follow-up, você perguntou sobre o desempenho relativo destas duas alternativas:

z1 = dict(x.items() + y.items())
z2 = dict(x, **y)

Na minha máquina, pelo menos (a x86_64 execução Python bastante comum 2.5.2), alternativa z2não é apenas mais curto e mais simples, mas também significativamente mais rápido. Você pode verificar isso por si mesmo usando o timeitmódulo que vem com Python.

Exemplo 1: dicionários idênticos mapeamento 20 inteiros consecutivos para si:

% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z1=dict(x.items() + y.items())'
100000 loops, best of 3: 5.67 usec per loop
% python -m timeit -s 'x=y=dict((i,i) for i in range(20))' 'z2=dict(x, **y)' 
100000 loops, best of 3: 1.53 usec per loop

z2ganha por um factor de 3,5 ou menos. Diferentes dicionários parecem produzir resultados bastante diferentes, mas z2sempre parece sair na frente. (Se você receber resultados inconsistentes para o mesmo teste, tente passando -rcom um número maior que o padrão 3.)

Exemplo 2: dicionários não sobrepostos mapeamento 252 cadeias curtas a números inteiros e vice-versa:

% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z1=dict(x.items() + y.items())'
1000 loops, best of 3: 260 usec per loop
% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z2=dict(x, **y)'               
10000 loops, best of 3: 26.9 usec per loop

z2 ganha por um fator de 10. Isso é um bem grande vitória no meu livro!

Depois de comparar os dois, eu me perguntava se z1é mau desempenho pode ser atribuído à sobrecarga de construir as duas listas de itens, que por sua vez me levaram a me perguntar se esta variação pode funcionar melhor:

from itertools import chain
z3 = dict(chain(x.iteritems(), y.iteritems()))

Alguns testes rápidos, por exemplo,

% python -m timeit -s 'from itertools import chain; from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z3=dict(chain(x.iteritems(), y.iteritems()))'
10000 loops, best of 3: 66 usec per loop

levam-me a concluir que z3é um pouco mais rápido do que z1, mas não tão rápido quanto z2. Definitivamente não vale toda a digitação extra.

Essa discussão ainda está faltando alguma coisa importante, que é uma comparação dessas alternativas com a maneira "óbvia" de fundir duas listas desempenho: usando o updatemétodo. Para tentar manter as coisas em pé de igualdade com as expressões, nenhum dos quais modificam x ou y, eu vou fazer uma cópia de x em vez de modificá-lo no local, como segue:

z0 = dict(x)
z0.update(y)

Um resultado típico:

% python -m timeit -s 'from htmlentitydefs import codepoint2name as x, name2codepoint as y' 'z0=dict(x); z0.update(y)'
10000 loops, best of 3: 26.9 usec per loop

Em outras palavras, z0e z2parecem ter um desempenho essencialmente idênticos. Você acha que isso pode ser uma coincidência? Eu não....

Na verdade, eu iria tão longe como a alegação de que é impossível para o código Python puro para fazer melhor do que isso. E se você pode fazer significativamente melhor em um módulo de extensão C, imagino as pessoas Python poderia muito bem estar interessado em incorporar o seu código (ou uma variação sobre a sua abordagem) para o núcleo Python. Python usa dictem muitos lugares; otimizando suas operações é um grande negócio.

Você também pode escrever isso como

z0 = x.copy()
z0.update(y)

como Tony faz, mas (não surpreendentemente) a diferença de notação acaba por não ter qualquer efeito mensurável sobre o desempenho. Use o que parece certo para você. Claro, ele está absolutamente correto em apontar que a versão de dois afirmação é muito mais fácil de entender.

Respondeu 23/10/2008 em 03:38
fonte usuário

votos
85

Eu queria algo semelhante, mas com a capacidade de especificar como os valores em chaves duplicadas foram fundidas, então eu hackeado isso (mas não muito testá-lo). Obviamente, isso não é uma única expressão, mas é uma única chamada de função.

def merge(d1, d2, merge_fn=lambda x,y:y):
    """
    Merges two dictionaries, non-destructively, combining 
    values on duplicate keys as defined by the optional merge
    function.  The default behavior replaces the values in d1
    with corresponding values in d2.  (There is no other generally
    applicable merge strategy, but often you'll have homogeneous 
    types in your dicts, so specifying a merge technique can be 
    valuable.)

    Examples:

    >>> d1
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1)
    {'a': 1, 'c': 3, 'b': 2}
    >>> merge(d1, d1, lambda x,y: x+y)
    {'a': 2, 'c': 6, 'b': 4}

    """
    result = dict(d1)
    for k,v in d2.iteritems():
        if k in result:
            result[k] = merge_fn(result[k], v)
        else:
            result[k] = v
    return result
Respondeu 04/09/2008 em 20:08
fonte usuário

votos
70

Em Python 3, você pode usar collections.ChainMap quais grupos múltiplas dicts ou outros mapeamentos em conjunto para criar uma visão única, atualizável:

>>> from collections import ChainMap
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = ChainMap({}, y, x)
>>> for k, v in z.items():
        print(k, '-->', v)

a --> 1
b --> 10
c --> 11
Respondeu 28/04/2013 em 04:15
fonte usuário

votos
59

Recursively / atualizar profunda um dicionário

def deepupdate(original, update):
    """
    Recursively update a dict.
    Subdict's won't be overwritten but also updated.
    """
    for key, value in original.iteritems(): 
        if key not in update:
            update[key] = value
        elif isinstance(value, dict):
            deepupdate(value, update[key]) 
    return update

demonstração:

pluto_original = {
    'name': 'Pluto',
    'details': {
        'tail': True,
        'color': 'orange'
    }
}

pluto_update = {
    'name': 'Pluutoo',
    'details': {
        'color': 'blue'
    }
}

print deepupdate(pluto_original, pluto_update)

saídas:

{
    'name': 'Pluutoo',
    'details': {
        'color': 'blue',
        'tail': True
    }
}

Graças rednaw para edições.

Respondeu 29/11/2011 em 12:52
fonte usuário

votos
54

A melhor versão que eu conseguia pensar enquanto não usando a cópia seria:

from itertools import chain
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
dict(chain(x.iteritems(), y.iteritems()))

É mais rápido do que dict(x.items() + y.items()), mas não tão rápido como n = copy(a); n.update(b), pelo menos no CPython. Esta versão também funciona em Python 3, se você mudar iteritems()para items(), o que é feito automaticamente pela ferramenta 2to3.

Pessoalmente eu gosto desta versão melhor porque descreve bastante boa o que eu quero em uma única sintaxe funcional. O único problema menor é que ele não faz completamente óbvio que os valores de y tem precedência sobre valores de x, mas eu não acredito que é difícil de descobrir isso.

Respondeu 14/10/2010 em 19:55
fonte usuário

votos
41

Python 3,5 (PEP 448) permite que uma opção melhor sintaxe:

x = {'a': 1, 'b': 1}
y = {'a': 2, 'c': 2}
final = {**x, **y} 
final
# {'a': 2, 'b': 1, 'c': 2}

ou mesmo

final = {'a': 1, 'b': 1, **x, **y}
Respondeu 26/02/2015 em 21:27
fonte usuário

votos
40
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

Para os itens com chaves em ambos os dicionários ( 'b'), você pode controlar quais um acaba na saída, colocando que uma última.

Respondeu 02/09/2008 em 08:49
fonte usuário

votos
34

Enquanto a questão já foi respondida várias vezes, esta solução simples para o problema ainda não foi listado.

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z4 = {}
z4.update(x)
z4.update(y)

É tão rápido quanto z0 e os z2 maus mencionados acima, mas fácil de entender e mudar.

Respondeu 14/10/2011 em 17:12
fonte usuário

votos
31
def dict_merge(a, b):
  c = a.copy()
  c.update(b)
  return c

new = dict_merge(old, extras)

Entre essas respostas obscuros e duvidosos, este brilhante exemplo é a primeira e única boa maneira de mesclar dicts em Python, aprovado pelo ditador vitalício Guido van Rossum si mesmo! Alguém sugeriu metade deste, mas não colocá-lo em uma função.

print dict_merge(
      {'color':'red', 'model':'Mini'},
      {'model':'Ferrari', 'owner':'Carl'})

dá:

{'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'}
Respondeu 06/08/2012 em 10:24
fonte usuário

votos
24

Se você acha que lambdas são maus, então não leia mais. Conforme solicitado, você pode escrever a solução rápida e eficiente para a memória com uma expressão:

x = {'a':1, 'b':2}
y = {'b':10, 'c':11}
z = (lambda a, b: (lambda a_copy: a_copy.update(b) or a_copy)(a.copy()))(x, y)
print z
{'a': 1, 'c': 11, 'b': 10}
print x
{'a': 1, 'b': 2}

Como sugerido acima, utilizando duas linhas ou escrever uma função é provavelmente a melhor maneira de ir.

Respondeu 23/11/2011 em 19:08
fonte usuário

votos
18

Em python3, o itemsmétodo não retorna uma lista , mas sim uma visão , que age como um conjunto. Neste caso, você precisa tomar a união de conjunto desde concatenando com +não vai funcionar:

dict(x.items() | y.items())

Para o comportamento python3-como na versão 2.7, o viewitemsmétodo deve funcionar no lugar de items:

dict(x.viewitems() | y.viewitems())

Eu prefiro esta notação de qualquer maneira, já que parece mais natural pensar nisso como uma operação de conjunto união, em vez de concatenação (como o título indica).

Editar:

Um casal mais pontos para python 3. Primeiro, note que o dict(x, **y)truque não funciona em python 3 a menos que as chaves ysão strings.

Além disso, Chainmap de Raymond Hettinger resposta é muito elegante, uma vez que pode ter um número arbitrário de dicts como argumentos, mas a partir dos docs parece que sequencialmente olha através de uma lista de todos os dicts para cada pesquisa:

Pesquisas procurar os mapeamentos subjacentes sucessivamente até que uma tecla é encontrado.

Isso pode atrasá-lo se você tem um monte de pesquisas na sua aplicação:

In [1]: from collections import ChainMap
In [2]: from string import ascii_uppercase as up, ascii_lowercase as lo; x = dict(zip(lo, up)); y = dict(zip(up, lo))
In [3]: chainmap_dict = ChainMap(y, x)
In [4]: union_dict = dict(x.items() | y.items())
In [5]: timeit for k in union_dict: union_dict[k]
100000 loops, best of 3: 2.15 µs per loop
In [6]: timeit for k in chainmap_dict: chainmap_dict[k]
10000 loops, best of 3: 27.1 µs per loop

Assim, cerca de uma ordem de magnitude mais lenta para pesquisas. Eu sou um fã de Chainmap, mas parece menos prático, onde pode haver muitas pesquisas.

Respondeu 09/10/2013 em 19:09
fonte usuário

votos
16

Seja pythônico. Use uma compreensão :

z={i:d[i] for d in [x,y] for i in d}

>>> print z
{'a': 1, 'c': 11, 'b': 10}
Respondeu 20/01/2016 em 11:46
fonte usuário

votos
14

Abuso levando a uma solução de uma expressão para a resposta de Mateus :

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (lambda f=x.copy(): (f.update(y), f)[1])()
>>> z
{'a': 1, 'c': 11, 'b': 10}

Você disse que queria uma expressão, então eu abusado lambdade ligar um nome, e tuplas para substituir limite de um expressão de lambda. Sinta-se livre para encolher.

Você também pode fazer isso, claro, se você não se preocupam com copiá-lo:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (x.update(y), x)[1]
>>> z
{'a': 1, 'b': 10, 'c': 11}
Respondeu 07/08/2013 em 22:23
fonte usuário

votos
13

solução simples usando itertools que preserva a ordem (este último dicts têm precedência)

import itertools as it
merge = lambda *args: dict(it.chain.from_iterable(it.imap(dict.iteritems, args)))

E é de uso:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> merge(x, y)
{'a': 1, 'b': 10, 'c': 11}

>>> z = {'c': 3, 'd': 4}
>>> merge(x, y, z)
{'a': 1, 'b': 10, 'c': 3, 'd': 4}
Respondeu 04/08/2015 em 14:54
fonte usuário

votos
12

dois dicionários

def union2(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

n dicionários

def union(*dicts):
    return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))

sumtem mau desempenho. veja https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/

Respondeu 17/10/2012 em 03:09
fonte usuário

votos
10

Mesmo que as respostas eram bons para este rasa dicionário, nenhum dos métodos definidos aqui realmente fazer uma mesclagem dicionário profundo.

Exemplos seguir:

a = { 'one': { 'depth_2': True }, 'two': True }
b = { 'one': { 'extra': False } }
print dict(a.items() + b.items())

Seria de esperar que um resultado de algo como isto:

{ 'one': { 'extra': False', 'depth_2': True }, 'two': True }

Em vez disso, ficamos com este:

{'two': True, 'one': {'extra': False}}

O 'um' entrada deve ter tido 'depth_2' e 'extra' como itens dentro de seu dicionário, se ele realmente foi uma mesclagem.

Usando cadeia também, não funciona:

from itertools import chain
print dict(chain(a.iteritems(), b.iteritems()))

Resulta em:

{'two': True, 'one': {'extra': False}}

A fusão profunda que rcwesick deu também cria o mesmo resultado.

Sim, ele vai trabalhar para mesclar os dicionários de amostra, mas nenhum deles é um mecanismo genérico para mesclar. Vou atualizar isso mais tarde uma vez que eu escrever um método que faz uma verdadeira mesclagem.

Respondeu 04/08/2012 em 00:36
fonte usuário

votos
9

Em python 3:

import collections
a = {1: 1, 2: 2}
b = {2: 3, 3: 4}
c = {3: 5}

r = dict(collections.ChainMap(a, b, c))
print(r)

Fora:

{1: 1, 2: 2, 3: 4}

Docs: https://docs.python.org/3/library/collections.html#collections.ChainMap :

Respondeu 24/05/2017 em 07:24
fonte usuário

votos
9

Para Python 2:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()+y.items())
print(z)

Para Python 3:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()|y.items())
print(z)

Dá saída:{'a': 1, 'c': 11, 'b': 10}

Respondeu 31/08/2016 em 13:53
fonte usuário

votos
9
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> x, z = dict(x), x.update(y) or x
>>> x
{'a': 1, 'b': 2}
>>> y
{'c': 11, 'b': 10}
>>> z
{'a': 1, 'c': 11, 'b': 10}
Respondeu 13/11/2013 em 11:01
fonte usuário

votos
8

Baseando-se em ideias aqui e em outros lugares que eu compreendia uma função:

def merge(*dicts, **kv): 
      return { k:v for d in list(dicts) + [kv] for k,v in d.items() }

Uso (testado em python 3):

assert (merge({1:11,'a':'aaa'},{1:99, 'b':'bbb'},foo='bar')==\
    {1: 99, 'foo': 'bar', 'b': 'bbb', 'a': 'aaa'})

assert (merge(foo='bar')=={'foo': 'bar'})

assert (merge({1:11},{1:99},foo='bar',baz='quux')==\
    {1: 99, 'foo': 'bar', 'baz':'quux'})

assert (merge({1:11},{1:99})=={1: 99})

Você poderia usar um lambda em vez.

Respondeu 19/07/2013 em 06:49
fonte usuário

votos
6

Você pode usar toolz.merge([x, y])para isso.

Respondeu 18/11/2016 em 12:53
fonte usuário

votos
6

Em Python 3.5 você pode usar descompactar **, a fim de criar um novo dicionário. Este método tem sido não mostrou em respostas anteriores. Além disso, é melhor usar {}em vez de dict(). Porque {}é um python literal e dict()envolve uma chamada de função.

dict1 = {'a':1}
dict2 = {'b':2}
new_dict = {**dict1, **dict2}
>>>new_dict
{'a':1, 'a':2}
Respondeu 28/09/2016 em 00:33
fonte usuário

votos
6

(Para Python2.7 * única, existem soluções mais simples para Python3 *.)

Se você não é avesso a importação de um módulo de biblioteca padrão, você pode fazer

from functools import reduce

def merge_dicts(*dicts):
    return reduce(lambda a, d: a.update(d) or a, dicts, {})

(O or abit na lambdaé necessário porque dict.updatesempre retorna Noneem caso de sucesso.)

Respondeu 28/03/2016 em 13:13
fonte usuário

votos
6

O problema que tenho com as soluções indicadas até à data é que, no dicionário mesclado, o valor para a chave "b" é 10, mas, no meu modo de pensar, que deve ser 12. A essa luz, eu apresento o seguinte:

import timeit

n=100000
su = """
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
"""

def timeMerge(f,su,niter):
    print "{:4f} sec for: {:30s}".format(timeit.Timer(f,setup=su).timeit(n),f)

timeMerge("dict(x, **y)",su,n)
timeMerge("x.update(y)",su,n)
timeMerge("dict(x.items() + y.items())",su,n)
timeMerge("for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k] ",su,n)

#confirm for loop adds b entries together
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]
print "confirm b elements are added:",x

Resultados:

0.049465 sec for: dict(x, **y)
0.033729 sec for: x.update(y)                   
0.150380 sec for: dict(x.items() + y.items())   
0.083120 sec for: for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]

confirm b elements are added: {'a': 1, 'c': 11, 'b': 12}
Respondeu 03/12/2013 em 19:11
fonte usuário

votos
5
from collections import Counter
dict1 = {'a':1, 'b': 2}
dict2 = {'b':10, 'c': 11}
result = dict(Counter(dict1) + Counter(dict2))

Isso deve resolver o seu problema.

Respondeu 30/11/2015 em 13:04
fonte usuário

votos
5

Isso pode ser feito com um único compreensão dict:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> { key: y[key] if key in y else x[key]
      for key in set(x) + set(y)
    }

Em minha opinião, a melhor resposta para a parte 'única expressão' como há funções extras são necessários, e é curto.

Respondeu 17/07/2015 em 14:47
fonte usuário

votos
5

Usando uma compreensão dict, você pode

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

dc = {xi:(x[xi] if xi not in list(y.keys()) 
           else y[xi]) for xi in list(x.keys())+(list(y.keys()))}

>>> dc
{'a': 1, 'c': 11, 'b': 10}

Observe a sintaxe para if elsea compreensão

{ (some_key if condition else default_key):(something_if_true if condition 
          else something_if_false) for key, value in dict_.items() }
Respondeu 27/05/2013 em 10:04
fonte usuário

votos
4

em python2

dict(mydict, **other)

ou

In [11]: dict({1:2}.items() + {2:3}.items() + {1:5}.items() )
Out[11]: {1: 5, 2: 3}

python3

{ **mydict, **otherdict}
Respondeu 28/06/2018 em 12:33
fonte usuário

votos
4

Eu sei que isto não se encaixa as especificidades das perguntas ( "one liner"), mas desde que nenhum das respostas acima entrou nesta direção enquanto muitas e muitas respostas abordou o problema de desempenho, eu senti que deveria contribuir meus pensamentos.

Dependendo do caso de uso pode não ser necessário criar um dicionário mesclado "real" dos dados dicionários de entrada. A vista que faz isso pode ser suficiente em muitos casos, ou seja, um objeto que age como o dicionário resultante da fusão não se computando-lo completamente. Uma versão preguiçosa do dicionário mesclado, por assim dizer.

Em Python, isso é bastante simples e pode ser feito com o código mostrado no final do meu post. Este dado, a resposta à pergunta inicial seria:

z = MergeDict(x, y)

Ao usar este novo objeto, ele irá se comportar como um dicionário mesclado mas terá tempo de criação constante e consumo de memória constante, deixando os dicionários originais intactas. Criação é a maneira mais barata do que nas outras soluções propostas.

Claro, se você usar o resultado muito, então você vai em algum ponto atingir o limite onde a criação de um dicionário mesclado verdadeira teria sido a solução mais rápida. Como eu disse, isso depende do seu caso de uso.

Se você já sentiu que preferiria ter um verdadeiro fundiu dict, em seguida, chamar dict(z)iria produzi-lo (mas muito mais caro do que as outras soluções, é claro, então este é apenas vale a pena mencionar).

Você também pode usar essa classe para fazer uma espécie de dicionário de copy-on-write:

a = { 'x': 3, 'y': 4 }
b = MergeDict(a)  # we merge just one dict
b['x'] = 5
print b  # will print {'x': 5, 'y': 4}
print a  # will print {'y': 4, 'x': 3}

Aqui está o código direto de MergeDict:

class MergeDict(object):
  def __init__(self, *originals):
    self.originals = ({},) + originals[::-1]  # reversed

  def __getitem__(self, key):
    for original in self.originals:
      try:
        return original[key]
      except KeyError:
        pass
    raise KeyError(key)

  def __setitem__(self, key, value):
    self.originals[0][key] = value

  def __iter__(self):
    return iter(self.keys())

  def __repr__(self):
    return '%s(%s)' % (
      self.__class__.__name__,
      ', '.join(repr(original)
          for original in reversed(self.originals)))

  def __str__(self):
    return '{%s}' % ', '.join(
        '%r: %r' % i for i in self.iteritems())

  def iteritems(self):
    found = set()
    for original in self.originals:
      for k, v in original.iteritems():
        if k not in found:
          yield k, v
          found.add(k)

  def items(self):
    return list(self.iteritems())

  def keys(self):
    return list(k for k, _ in self.iteritems())

  def values(self):
    return list(v for _, v in self.iteritems())
Respondeu 18/05/2016 em 15:57
fonte usuário

votos
4

É tão bobo que .updatenão retorna nada.
Eu só usar uma função auxiliar simples para resolver o problema:

def merge(dict1,*dicts):
    for dict2 in dicts:
        dict1.update(dict2)
    return dict1

Exemplos:

merge(dict1,dict2)
merge(dict1,dict2,dict3)
merge(dict1,dict2,dict3,dict4)
merge({},dict1,dict2)  # this one returns a new copy
Respondeu 02/03/2014 em 02:44
fonte usuário

votos
3
a = {1: 2, 3: 4, 5: 6}
b = {7:8, 1:2}
combined = dict(a.items() + b.items())
print combined
Respondeu 21/03/2015 em 00:06
fonte usuário

votos
2

Se você não se importa em mutação x,

x.update(y) or x

Simples e legível, performance. Você sabe update() sempre retorna None, que é um valor falso. Por isso, sempre irá avaliar a x.

Métodos de mutação na biblioteca padrão, como update, retorne Nonepor convenção, de modo que este truque irá funcionar em quem também.

Se você estiver usando uma biblioteca que não segue esta convenção, você pode usar um monitor de tupla e índice para torná-lo uma única expressão, em vez de or, mas não é tão legível.

(x.update(y), x)[-1]

Se você não tem xem uma variável, no entanto, você pode usar lambdapara fazer um local sem usando um comando de atribuição. Isso equivale a usar lambdacomo uma expressão let , que é uma técnica comum em linguagens funcionais, mas sim unpythonic.

(lambda x: x.update(y) or x)({'a':1, 'b': 2})

Se você quer uma cópia, PEP 448 é melhor {**x, **y}. Mas se isso não é disponível, vamos obras aqui também.

(lambda z: z.update(y) or z)(x.copy())
Respondeu 22/09/2017 em 02:57
fonte usuário

votos
2

Eu tenho uma solução que não é especificado aqui (Man I Love python) :-)

z = {}
z.update(x) or z.update(y)

Isso não vai atualizar x, bem como y. Atuação? Eu não acho que vai ser :-) terrivelmente lento

NOTA: É suposto ser 'ou' operação e não 'e' operação. Editado para corrigir o código.

Respondeu 05/12/2013 em 09:02
fonte usuário

votos
1

trecho de código - mais recente

pitão 3.6. *

d1 = {"a":1,"b":2,"c":3}
d2 = {"d":4,"e":5,"f":6}
d3 = {"g":7,"h":8,"j":9}
d4 = {'wtf':'yes'}

d1a = {"a":1,"b":2,"c":3}
d1b = {"a":2,"b":3,"c":4}
d1c = {"a":3,"b":4,"c":5}
d1d = {"a":"wtf"}

def dics_combine(*dics):
    dic_out = {}
    for d in dics:
        if isinstance(d, dict):
            dic_out = {**dic_out, **d}
        else:
            pass
    return dic_out

inp = (d1,d2,d3,d4)
combined_dics = dics_combine(*inp)
print('\n')
print('IN-ORDER: {0}'.format(inp))
print('OUT: {0}'.format(combined_dics))

inp = (d1a,d1b,d1c,d1d)
combined_dics = dics_combine(*inp)
print('\n')
print('IN-ORDER: {0}'.format(inp))
print('OUT: {0}'.format(combined_dics))

inp = (d1d,d1c,d1b,d1a)
combined_dics = dics_combine(*inp)
print('\n')
print('IN-ORDER: {0}'.format(inp))
print('OUT: {0}'.format(combined_dics)))

EM-PEDIDO: ({ 'a': 1, 'b': 2, 'c': 3}, {? D ': 4, 'E': 5, 'F': 6}, { 'g': 7, 'h': 8, 'j': 9}, { 'wtf': 'sim'})

OUT: { 'a': 1, 'b': 2 'c': 3, 'd': 4, 'E': 5, 'F': 6, 'g': 7, 'h': 8 , 'j': 9, 'wtf': 'sim'}

EM-PEDIDO: ({ 'a': 1, 'b': 2, 'c': 3}, { 'uma': 2 'b': 3, 'c': 4}, { 'a': 3, 'b': 4, 'c': 5}, { 'a': 'wtf'})

OUT: { 'a': 'wtf', 'b': 4, 'c': 5}

EM-PEDIDO: ({ 'a': 'wtf'}, { 'uma': 3, 'b': 4, 'c': 5}, { 'uma': 2 'b': 3, 'c ': 4}, {' a ': 1, 'b': 2, 'c': 3})

OUT: { 'a': 1, 'b': 2, 'c': 3}

Respondeu 07/02/2018 em 22:05
fonte usuário

votos
1

A questão é marcado python-3x, mas, tendo em conta que é uma adição relativamente recente e que o mais votado, aceitou ofertas resposta extensivamente com uma solução Python 2.x, ouso acrescentar um um forro que se baseia em uma característica irritante de Python 2.x compreensão da lista, que é nome de vazamento ...

$ python2
Python 2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> [z.update(d) for z in [{}] for d in (x, y)]
[None, None]
>>> z
{'a': 1, 'c': 11, 'b': 10}
>>> ...

Estou feliz em dizer que o acima não funciona mais em qualquer versão do Python 3.

Respondeu 30/05/2017 em 12:28
fonte usuário

votos
1

A união de dois dicionários do OP seria algo como:

{'a': 1, 'b': 2, 10, 'c': 11}

Especificamente, a união de duas entidades ( xe y) contém todos os elementos de xe / ou y. Infelizmente, o que o OP pede não é uma união, apesar do título do post.

Meu código abaixo não é nem elegante nem uma frase, mas eu acredito que é consistente com o significado de união.

Com o exemplo do OP:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

z = {}
for k, v in x.items():
    if not k in z:
        z[k] = [(v)]
    else:
        z[k].append((v))
for k, v in y.items():
    if not k in z:
        z[k] = [(v)]
    else:
        z[k].append((v))

{'a': [1], 'b': [2, 10], 'c': [11]}

Se alguém quiser listas poderia ser mudado, mas o acima funcionará se um dicionário contém listas (e listas aninhadas) como valores em qualquer dicionário.

Respondeu 30/09/2014 em 03:36
fonte usuário

votos
1

**cria um dict intermediário, o que significa que o número total de cópias é realmente superior fazendo a dict(one, **two)forma, mas tudo o que acontece em C, então ainda é geralmente mais rápido do que ir a itertools, a menos que há um grande número de cópias (ou, provavelmente, se as cópias são muito caros). Como sempre, se você realmente se preocupam com a velocidade que você deve tempo seu caso de uso.

Sincronismo em Python 2.7.3 com um Dict vazio:

$ python -m timeit "dict({}, **{})"
1000000 loops, best of 3: 0.405 usec per loop

$ python -m timeit -s "from itertools import chain" \
    "dict(chain({}.iteritems(), {}.iteritems()))"
1000000 loops, best of 3: 1.18 usec per loop

Com 10.000 (pequenos) itens:

$ python -m timeit -s 'd = {i: str(i) for i in xrange(10000)}' \
    "dict(d, **d)"
1000 loops, best of 3: 550 usec per loop

$ python -m timeit -s "from itertools import chain" -s 'd = {i: str(i) for i in xrange(10000)}' \
    "dict(chain(d.iteritems(), d.iteritems()))"
1000 loops, best of 3: 1.11 msec per loop

Com 100.000 itens:

$ python -m timeit -s 'd = {i: str(i) for i in xrange(100000)}' \
    "dict(d, **d)"
10 loops, best of 3: 19.6 msec per loop

$ python -m timeit -s "from itertools import chain" -s 'd = {i: str(i) for i in xrange(100000)}' \
    "dict(chain(d.iteritems(), d.iteritems()))"
10 loops, best of 3: 20.1 msec per loop

Com 1.000.000 de itens:

$ python -m timeit -s 'd = {i: str(i) for i in xrange(1000000)}' \
    "dict(d, **d)"
10 loops, best of 3: 273 msec per loop

$ python -m timeit -s "from itertools import chain" -s 'd = {i: str(i) for i in xrange(1000000)}' \
    "dict(chain(d.iteritems(), d.iteritems()))"
10 loops, best of 3: 233 msec per loop
Respondeu 06/09/2013 em 21:18
fonte usuário

votos
0

Acho que meus feias one-liners são apenas necessários aqui.

z = next(z.update(y) or z for z in [x.copy()])
# or
z = (lambda z: z.update(y) or z)(x.copy())
  1. Dicts são mesclados.
  2. expressão única.
  3. Nunca se atreve a usá-lo.
Respondeu 11/05/2018 em 10:00
fonte usuário

votos
0

Onde está o problema no seu código?

Em Python, dicionário é definido como uma coleção desordenada de chave-valor itens emparelhados onde as chaves são objetos únicos e imutáveis.

O update()método atualiza o objeto de dicionário chamada, ou seja, xcom o conteúdo passando dicionário de objetos ie y.

Se encontrar qualquer chave duplicada no objeto de chamada em seguida, ele irá substituir o seu valor com o valor correspondente à chave combinado de passar objeto.

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

Então você vai ficar {'a': 1, 'b': 10, 'c': 11}no lugar de ficar{'a': 1, 'b': 10, 'c': 11, 'b': 2}

Use compreensão dicionário para resolver

A maneira profissional para criar dicionários usando dicionários existentes ou outros objetos iteradores.

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>>
>>> my_dicts = (x, y);  # Gathering all dictionaries in a tuple/list
>>> z = {key: value for my_dict in my_dicts for key, value in my_dict.iteritems()}; # Single line of code that creates new dictionary object from existing dictionaries
>>> z
{'a': 1, 'c': 11, 'b': 10}

Referências

https://www.datacamp.com/community/tutorials/python-dictionary-comprehension

Obrigado.

Respondeu 07/05/2018 em 06:53
fonte usuário

votos
0

Esta é uma expressão para o Python 3.5 ou maior que funde dicionários usando reduce:

>>> from functools import reduce
>>> l = [{'a': 1}, {'b': 2}, {'a': 100, 'c': 3}]
>>> reduce(lambda x, y: {**x, **y}, l, {})
{'a': 100, 'b': 2, 'c': 3}

Nota: isso funciona mesmo se a lista de dicionários está vazio ou contém apenas um elemento.

Respondeu 15/04/2018 em 23:02
fonte usuário

votos
0

Eu estava curioso para saber se eu poderia bater o tempo da resposta aceita com uma abordagem stringify uma linha:

Eu tentei 5 métodos, nenhum mencionado anteriormente - todo um forro - todos os que produzem respostas corretas - e eu não podia chegar perto.

Então ... para salvar-lhe a dificuldade e talvez cumprir curiosidade:

import json
import yaml
import time
from ast import literal_eval as literal

def merge_two_dicts(x, y):
    z = x.copy()   # start with x's keys and values
    z.update(y)    # modifies z with y's keys and values & returns None
    return z

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

start = time.time()
for i in range(10000):
    z = yaml.load((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify yaml')

start = time.time()
for i in range(10000):
    z = literal((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify literal')

start = time.time()
for i in range(10000):
    z = eval((str(x)+str(y)).replace('}{',', '))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify eval')

start = time.time()
for i in range(10000):
    z = {k:int(v) for k,v in (dict(zip(
            ((str(x)+str(y))
            .replace('}',' ')
            .replace('{',' ')
            .replace(':',' ')
            .replace(',',' ')
            .replace("'",'')
            .strip()
            .split('  '))[::2], 
            ((str(x)+str(y))
            .replace('}',' ')
            .replace('{',' ').replace(':',' ')
            .replace(',',' ')
            .replace("'",'')
            .strip()
            .split('  '))[1::2]
             ))).items()}
elapsed = (time.time()-start)
print (elapsed, z, 'stringify replace')

start = time.time()
for i in range(10000):
    z = json.loads(str((str(x)+str(y)).replace('}{',', ').replace("'",'"')))
elapsed = (time.time()-start)
print (elapsed, z, 'stringify json')

start = time.time()
for i in range(10000):
    z = merge_two_dicts(x, y)
elapsed = (time.time()-start)
print (elapsed, z, 'accepted')

resultados:

7.693928956985474 {'c': 11, 'b': 10, 'a': 1} stringify yaml
0.29134678840637207 {'c': 11, 'b': 10, 'a': 1} stringify literal
0.2208399772644043 {'c': 11, 'b': 10, 'a': 1} stringify eval
0.1106564998626709 {'c': 11, 'b': 10, 'a': 1} stringify replace
0.07989692687988281 {'c': 11, 'b': 10, 'a': 1} stringify json
0.005082368850708008 {'c': 11, 'b': 10, 'a': 1} accepted

o que eu fiz aprender com isto é que jsonabordagem é a maneira mais rápida (dos que tentou) para retornar um dicionário de corda-de-dicionário; muito mais rápido (cerca de 1/4 do tempo) do que eu considerava ser o método normal usando ast. Aprendi também que, a yamlabordagem deve ser evitado a todo o custo.

Sim, eu entendo que isso não é a melhor maneira / correta por isso, não downvote ao esquecimento negativo, zero é apenas multa. Eu estava curioso para saber se ele foi mais rápido, o que não é; Eu postei para prová-lo assim.

Respondeu 22/03/2018 em 04:08
fonte usuário

votos
-3

x = { "a": 1}

y = { "b": 2}

x.update (y)

print x # { 'a': 1, 'b': 2}

Respondeu 20/11/2017 em 11:53
fonte usuário

votos
-3

Aqui está um código, parece funcionar ok:

def merge(d1, d2, mode=0):
    if not type(d2) is dict:
        raise Exception("d2 is not a dict")

    if not type(d1) is dict:
        if mode == 0:
            raise Exception("d1 is not a dict")
        return d2

    result = dict(d1)

    for k, v in d2.iteritems():
        if k in result and type(v) is dict:
            result[k] = merge(result[k], v, 1)
        else:
            if mode == 1:
                result.update(d2)
            else:
                result[k] = v
    return result
Respondeu 11/07/2013 em 08:13
fonte usuário

votos
-4
dictionaries = [{'body': 'text'},
{'correctAnswer': 'text'},
{'ans': 'text'},
{'ans': 'text'}]

final_dictionary = {}
for dictionary in dictionaries:
    for key in dictionary:
        final_dictionary[key] = dictionary[key]

print(final_dictionary)

Parece que você é muito novo para Python, então a solução que eu sugiro é a citada acima, que eu acho que é mais legível para alguém que só conhece para-loops, e interagindo sobre as chaves de um dicionário. O pseudo-código é como se segue:

for each of the dictionaries in the list: 
    add each of the key-value pairs in that dictionary to our final dictionary.
Respondeu 04/12/2017 em 22:56
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more