¿Cómo concatenar dos diccionarios para crear uno nuevo? [duplicate]

5 minutos de lectura

avatar de usuario
Timy

Digamos que tengo tres dictados

d1={1:2,3:4}
d2={5:6,7:9}
d3={10:8,13:22}

¿Cómo puedo crear un nuevo d4 que combina estos tres diccionarios? es decir:

d4={1:2,3:4,5:6,7:9,10:8,13:22}

  • d4 = {**d1, **d2, **d3} –> {1: 2, 3: 4, 5: 6, 7: 9, 10: 8, 13: 22}

    – muyad

    23 de mayo de 2020 a las 10:51


avatar de usuario
alex martelli

  1. Más lento y no funciona en Python3: concatenar el items y llama dict en la lista resultante:

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1.items() + d2.items() + d3.items())'
    
    100000 loops, best of 3: 4.93 usec per loop
    
  2. Más rápido: explotar el dict constructor hasta la empuñadura, entonces uno update:

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1, **d2); d4.update(d3)'
    
    1000000 loops, best of 3: 1.88 usec per loop
    
  3. Intermedio: un bucle de update llama a un dict inicialmente vacío:

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = {}' 'for d in (d1, d2, d3): d4.update(d)'
    
    100000 loops, best of 3: 2.67 usec per loop
    
  4. O, de manera equivalente, un copy-ctor y dos actualizaciones:

    $ python -mtimeit -s'd1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}' \
    'd4 = dict(d1)' 'for d in (d2, d3): d4.update(d)'
    
    100000 loops, best of 3: 2.65 usec per loop
    

Recomiendo el enfoque (2), y particularmente recomiendo evitar (1) (que también ocupa O (N) memoria auxiliar adicional para la lista concatenada de elementos de la estructura de datos temporales).

  • no entiendo porque d4 = dict(d1, **dict(d2, **d3)) no es más rápido que el #2, pero no lo es.

    –Robert Rossney

    23 de noviembre de 2009 a las 18:29

  • 1 anterior es mejor si se trabaja en pequeños dictados, ya que es más claro en mi opinión.

    – Baz

    28 de febrero de 2012 a las 20:13

  • A menos que se sepa que todas las claves son cadenas, la opción 2 es un abuso de un detalle de implementación de Python 2 (el hecho de que algunas funciones integradas implementadas en C omitieron las verificaciones esperadas en los argumentos de palabras clave). En Python 3 (y en PyPy), la opción 2 fallará con claves que no sean cadenas.

    –Carl Meyer

    30 de marzo de 2013 a las 23:09

  • agregaría eso d1.items() + d2.items() no funciona en Python 3.

    – Francisco

    10/01/2017 a las 17:00

  • En Python 3.5+ uno puede usar el ** notación: d1={1:2,3:4}; d2={5:6,7:9}; d3={10:8,13:22}; d4 = {**d1, **d2, **d3}, que para mí fue casi 3 veces más rápido que el n.° 3 o el n.° 4 anteriores (0,228 usec por ciclo frente a 0,661 o 0,595 usec para el n.° 3 o 4, respectivamente). Como se mencionó anteriormente, los números 1 y 2 no funcionan en Python 3.

    – jared

    12 de abril de 2018 a las 4:14

avatar de usuario
Ámbar

d4 = dict(d1.items() + d2.items() + d3.items())

alternativamente (y supuestamente más rápido):

d4 = dict(d1)
d4.update(d2)
d4.update(d3)

La pregunta SO anterior de la que provinieron ambas respuestas está aquí.

  • En vez de d4 = dict(d1) uno podría usar d4 = copy(d1).

    – Georg Scholly

    23 de noviembre de 2009 a las 7:49

  • @ds: Eso parece no funcionar. Tal vez quisiste decir from copy import copy; d4 = copy(d1) o quizás d4 = d1.copy().

    – John Maquin

    23 de noviembre de 2009 a las 9:05

  • La primera versión no funciona en Python3.

    – Supermejor

    6 de febrero de 2015 a las 3:37


  • Quizás d4 = d1.copy()

    – John Carrell

    16/10/2015 a las 19:15


  • Funciona en Python 3, pero tienes que emitir el dict_items objetos reales list objetos. Este es otro caso en el que Python 3 priorizó optimizaciones de rendimiento menores sobre la simplicidad y la facilidad de uso.

    –Carl Smith

    12 de abril de 2017 a las 13:26

Puedes usar el update() para construir un nuevo diccionario que contenga todos los elementos:

dall = {}
dall.update(d1)
dall.update(d2)
dall.update(d3)

O, en un bucle:

dall = {}
for d in [d1, d2, d3]:
  dall.update(d)

  • la actualización no crea un nuevo diccionario. (Como se esperaba) actualiza el original.

    – AJ Rouvoet

    06/02/2013 a las 17:30

  • @AJRouvoet: “El original” en este caso es un nuevo diccionario vacío en dall. Este nuevo diccionario se actualiza repetidamente para contener todos los elementos. es intencional que dall está cambiado.

    – algo

    6 de febrero de 2013 a las 17:38

  • Ah, mi comentario fue puramente sobre la forma en que expresaste la primera oración. Sugirió algo que no es el caso. Aunque admito que un voto negativo puede haber sido un poco duro.

    – AJ Rouvoet

    6 de febrero de 2013 a las 22:09

  • lógicamente, al usar la actualización, podemos crear un nuevo diccionario actualizando otro y, si no necesitamos el dic anterior, podemos eliminarlos usando del d1 en for loop.

    – Jay

    29 de octubre de 2017 a las 16:16

avatar de usuario
Ron Rothman

Aquí hay una sola línea (imports no cuente 🙂 que se puede generalizar fácilmente para concatenar N diccionarios:

Pitón 3

from itertools import chain
dict(chain.from_iterable(d.items() for d in (d1, d2, d3)))

y:

from itertools import chain
def dict_union(*args):
    return dict(chain.from_iterable(d.items() for d in args))

Pitón 2.6 y 2.7

from itertools import chain
dict(chain.from_iterable(d.iteritems() for d in (d1, d2, d3))

Producción:

>>> from itertools import chain
>>> d1={1:2,3:4}
>>> d2={5:6,7:9}
>>> d3={10:8,13:22}
>>> dict(chain.from_iterable(d.iteritems() for d in (d1, d2, d3)))
{1: 2, 3: 4, 5: 6, 7: 9, 10: 8, 13: 22}

Generalizado para concatenar N dictados:

from itertools import chain
def dict_union(*args):
    return dict(chain.from_iterable(d.iteritems() for d in args))

Llego un poco tarde a esta fiesta, lo sé, pero espero que esto ayude a alguien.

avatar de usuario
Shea Lafayette San Valentín

Usar el constructor de dictado

d1={1:2,3:4}
d2={5:6,7:9}
d3={10:8,13:22}

d4 = reduce(lambda x,y: dict(x, **y), (d1, d2, d3))

Como una función

from functools import partial
dict_merge = partial(reduce, lambda a,b: dict(a, **b))

La sobrecarga de crear diccionarios intermedios se puede eliminar usando eldict.update() método:

from functools import reduce
def update(d, other): d.update(other); return d
d4 = reduce(update, (d1, d2, d3), {})

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad