Saltar al contenido

Cómo Unir Dos Diccionarios en Python

Cómo Unir Dos Diccionarios en Python

A menudo nos encontramos en la situación de tener dos diccionarios o más que necesitamos fusionar en uno solo. Existen varias alternativas para lograr esto y podremos usar una u otra en función de nuestras necesidades y de la versión de Python que estemos usando. Te cuento todo esto y más en este artículo.

Para unir dos diccionarios A y B en uno nuevo C se hace lo siguiente:

  • En Python 3.9+: C = A | B.
  • En Python 3.5+: C = {**A, **B}.
  • Hasta Python 3.4: C = A.copy(); C.update(B).

Voy a detallar a continuación todas estas alternativas y algunas peculiaridades y situaciones que pueden suceder, como tener claves repetidas en los diccionarios a unir o tener una lista de diccionarios para combinar.

Antes de empezar a ver los diferentes métodos que tenemos para llevar a cabo nuestra tarea te voy a presentar los datos con los que trabajaremos.

Partamos de dos diccionarios A y B para lograr un nuevo diccionario C con los pares clave-valor de ambos. Estos son nuestros diccionarios:

A = {
    10: 'diez',
    20: 'veinte',
    40: 'cuarenta'
}

B = {
    30: 'treinta',
    50: 'cincuenta'
}

B2 = {
    20: 'veinte repetido',
    30: 'treinta'
}

Como puedes ver, he añadido un tercer diccionario B2 que contiene la clave 20 que también se encuentra en A. Así podremos estudiar qué sucede cuando tenemos claves repetidas en dos diccionarios que queremos fusionar.

¡Vamos allá!

Como unir dos diccionarios manualmente

Te voy a presentar aquí varias formas de unir diccionarios «manualmente», es decir, que haremos algoritmos para unir dos diccionarios sin utilizar determinadas características de Python, como si estuviéramos utilizando otro lenguaje.

Aunque finalmente intentaremos no hacer así las cosas, me parece importante contarlo aquí porque es muy interesante desde el punto de vista didáctico, sobre todo si llevas poco tiempo con Python o aprendiendo programación en general. Si no es así, puedes saltar a la siguiente sección.

Así, lo primero que se nos puede ocurrir es recorrer todos los pares de un diccionario para ir añadiéndolos al segundo. Para ello podemos hacer uso del método items que nos devuelve un objeto tipo conjunto de pares clave-valor de un diccionario para añadirlos al otro uno a uno. Es decir:

for clave, valor in B.items():
    A[clave] = valor

print(A)

Que nos dará el resultado esperado:

{10: 'diez', 20: 'veinte', 40: 'cuarenta', 30: 'treinta', 50: 'cincuenta'}

Cómo ves, es sencillo y bastante directo, y como te decía, sería la manera de hacerlo en otro lenguaje que no nos diera operadores para trabajar con diccionarios a otro nivel u otras características que veremos más adelante.

De todas maneras, esto no deja de tener el problema de que en realidad hemos modificado el diccionario A y no hemos obtenido un nuevo diccionario C. Para lograr esto tendríamos que modificar ligeramente nuestro algoritmo, realizando una copia de A. Lo vemos:

C = A.copy()

for clave, valor in B.items():
    C[clave] = valor

print(f'{A=}')
print(f'{C=}')

En el resultado vemos que A queda inalterado:

A={10: 'diez', 20: 'veinte', 40: 'cuarenta'}
C={10: 'diez', 20: 'veinte', 40: 'cuarenta', 30: 'treinta', 50: 'cincuenta'}

Recuerda que la función copy del diccionario nos devuelve una copia superficial, es decir, un nuevo diccionario con referencias a los elementos del antiguo y no copias de dichos elementos. Si necesitas una copia profunda puedes usar la función deepcopy de la librería copy de esta manera:

import copy

...

C = copy.deepcopy(A)

Pero, ¿qué pasa si tenemos elementos con claves repetidas en los dos diccionarios a unir? Pues sucederá que nuestro nuevo diccionario C contendrá los elementos, para aquellas claves repetidas, que se encuentren en el diccionario recorrido en el bucle. Es decir, que se actualizarán los valores del primer diccionario, el que hemos copiado, con los nuevos valores del diccionario recorrido.

15 conceptos fundamentales que necesitas conocer para aprender y dominar Python

Te voy a hacer dos regalos (no uno, sino dos) que hablan de estos 15 conceptos fundamentales de Python: mi Tutorial Básico Interactivo de Python y una cheat sheet de Python en español: La Hoja de Referencia de Python.

Estos regalos son exclusivos para los suscriptores de Código Pitón.

👍 Quiero mis dos regalos

Así, al ejecutar nuestro algoritmo con los diccionarios A y B2 obtendremos el siguiente resultado:

{10: 'diez', 20: 'veinte repetido', 40: 'cuarenta', 30: 'treinta'}

Si lo que queremos es mantener los valores, para claves repetidas, del diccionario A, tendremos que darle la vuelta a la tortilla:

C = B2.copy()

for clave, valor in A.items():
    C[clave] = valor

print(C)

Y el resultado será el siguiente:

{20: 'veinte', 30: 'treinta', 10: 'diez', 40: 'cuarenta'}

Cómo unir dos diccionarios con el operador «|» (Python 3.9+)

Veamos la manera más actual (en el momento de escribir esta líneas) para unir o combinar dos diccionarios en Python. Hay que tener en cuenta que esto funcionará en Python 3.9 o en versiones superiores.

Vamos a hacer uso del operador |. Puedes consultar mucha documentación sobre este operador en el documento de mejora de Python PEP 584.

Es una manera maravillosa y limpia de unir dos diccionarios. Lo vemos:

C = A | B

print(C)

Aquí el resultado:

{10: 'diez', 20: 'veinte', 40: 'cuarenta', 30: 'treinta', 50: 'cincuenta'}

¿Cómo se gestiona la situación de tener claves repetidas en los diccionarios? Hay que tener en cuenta que el operador | no es conmutativo, es decir, A | B y B | A pueden no ser lo mismo.

Así, si en el diccionario indicado como segundo operando en la expresión tiene una clave que ya está en el diccionario del primer operando, el elemento que permanecerá en el resultado final será el del segundo operando. Suena un poco a trabalenguas pero en el ejemplo quedará bien claro.

Vamos a comprobarlo realizando uniones entre A y B2, donde la clave 20 está repetida:

C = A | B2

print(C)

C = B2 | A

print(C)

El código anterior nos muestra lo siguiente por pantalla:

{10: 'diez', 20: 'veinte repetido', 40: 'cuarenta', 30: 'treinta'}
{20: 'veinte', 30: 'treinta', 10: 'diez', 40: 'cuarenta'}

Como puedes ver, en la primera versión de C el valor correspondiente a la clave 20 es veinte repetido, que se encontraba inicialmente en el diccionario B2.

En la segunda versión de C, el valor de la clave 20 es veinte, que pertenece al diccionario A.

Ten en cuenta esta característica de | cuando necesites unir dos diccionarios con Python 3.9+.

Cómo unir dos diccionarios desempaquetando con ** (Python 3.5+)

Desde Python 3.5 tenemos la posibilidad de desempaquetar diccionarios utilizando el operador de doble asterisco **.

Te cuento muchas cosas sobre los asteriscos, tanto simples como dobles, * y **, en el siguiente artículo: cómo usar los asteriscos en Python. No dejes de leerlo para aprender varios conceptos interesantes y profundizar en el lenguaje. Si lo deseas, puedes consultar la propuesta de mejora de Python 448.

Así, podemos desempaquetar todos los elementos de cada diccionario a unir en uno nuevo de la siguiente manera:

C = {**A, **B}

El resultado ya te lo imaginas.

Tratemos ahora el problema de los diccionarios con claves repetidas. Tenemos que poner de último en la expresión al diccionario del que queramos priorizar sus elementos. Es decir, si queremos que todos los elementos de un diccionario X estén en el nuevo diccionario, debemos ponerlo en el último lugar.

Lo vemos:

C = {**A, **B2}

print(C)

C = {**B2, **A}

print(C)

El resultado es el siguiente:

{10: 'diez', 20: 'veinte repetido', 40: 'cuarenta', 30: 'treinta'}
{20: 'veinte', 30: 'treinta', 10: 'diez', 40: 'cuarenta'}

En este sentido sucede igual que con el uso del operador |. Siempre se conservan todos los elementos del último diccionario con cualquiera de los dos métodos.

Cómo unir dos diccionarios en versiones antiguas (Python 3.4-)

Si tienes que trabajar con alguna versión Pthon 3.4 o inferior (incluidas las de Python 2) y no tienes la posibilidad de actualizarte (cosa que te recomiendo encarecidamente), te muestro aquí otra alternativa.

Vamos a hacer uso aquí de los métodos que nos brindan los diccionarios de Python. La función update de la clase dict nos permite actualizar un diccionario con los elementos de otro. Así, podríamos realizar la siguiente operación:

A.update(B)

print(A)

Y tendríamos:

{10: 'diez', 20: 'veinte', 40: 'cuarenta', 30: 'treinta', 50: 'cincuenta'}

Vemos que también en sencillo. No obstante nos encontramos con el problema de haber modificado A en lugar de tener un nuevo diccionario C. Para ello, al igual que hicimos en el primer apartado, podemos realizar previamente una copia. En este caso, realizaré una copia superficial para después hacer la llamada a update:

C = A.copy()
C.update(B)

¿Cómo funciona update en el caso de tener elementos con claves repetidas? Los elementos de claves ya existentes en el diccionario a actualizar son reemplazados. Así, si hacemos lo siguiente…

C = A.copy()
C.update(B2)

print(C)

C = B2.copy()
C.update(A)

print(C)

…obtendremos el siguiente resultado:

{10: 'diez', 20: 'veinte repetido', 40: 'cuarenta', 30: 'treinta'}
{20: 'veinte', 30: 'treinta', 10: 'diez', 40: 'cuarenta'}

Cómo no unir dos diccionarios

Recuerda que las opciones manuales están presentes en este artículo por motivos didácticos, pero no son las soluciones más apropiadas o las más eficientes. Por eso te invito a que utilices las otras alternativas presentadas previamente.

Además, quiero comentarte otras posibles soluciones que circulan por internet que también pueden no resultar adecuadas por un motivo u otro. Te las presento aquí brevemente por si tienes interés.

  • C = dict(A.items() + B.items()). Aunque puede parecer una buena forma de realizar la unión de diccionarios, este código genera tres listas diferentes en Python 2. La primera con los elementos de A, la segunda con los elementos de B y una tercera con todos los elementos de las dos anteriores al aplicar el operador +. Después se construye el diccionario y se descartan las tres listas. Esto parece un desperdicio de recursos computacionales. Además, en Python 3, la unión de items() no funcionará ya que esta función devuelve dos objetos (no dos listas) que no soportan la operación +. Aunque se podrían encapsular en una lista haciendo list(A.items()).
  • C = dict(A.items() | B.items()). Esta opción falla cuando los valores de los diccionarios no puede tener un valor de hash, como por ejemplo las listas u otro objeto para el cual no se puede definir. En caso de no ser así, igualmente fallaría esta opción ya que no podemos garantizar qué elemento se conservará en caso de claves repetidas. Esto es debido al orden arbitrario de los conjuntos. En Python 2 en lugar de items() se usaría la función viewitems().
  • C = dict(**A, **B) o C = dict(A, **B). Estas otras opciones usan el constructor de diccionarios teniendo en cuenta que reciben parámetros con nombre. Así, solo funcionarán en el caso de que las claves sean de tipo string. Nuevamente, puedes aprender más acerca de los parámetros con nombre en mi artículo sobre los asteriscos en Python. Además, parece ser que el creador de Python no acepta este uso concreto para el operador **.

Cómo unir una lista de diccionarios en uno solo

Si necesitamos unir más de dos diccionarios en uno solo podemos pensar en ubicar todos los diccionarios en una lista para pasar a unirlos después. Es decir, vamos a generalizar el problema para un número arbitrario de diccionarios.

Así, vamos a suponer que tenemos una lista de diccionarios llamada diccionarios con el siguiente aspecto:

A = { 1: 100, 2: 200, 3: 300}
B = { 2: 2000, 3: 3000, 4: 4000}
C = { 3: 30000, 4: 40000, 5: 50000}
D = { 4: 400000, 5: 600000, 6: 700000}

diccionarios = [A, B, C, D]

Ahora vamos a crear un diccionario union con la unión de todos ellos. Vamos a ir viendo la manera de realizarlos según los métodos de unión explicados previamente.

Con el operador |. Si tenemos Python 3.9+ podemos optar por unir todos los diccionarios de la lista de la siguiente manera, que consiste en crear un primer diccionario vacío y después ir uniendo el resto en un bucle:

union = {}

for d in diccionarios:
    union = union | d   # alternativa: union |= d

print(union)

Esto nos dará como resultado lo siguiente:

{1: 100, 2: 2000, 3: 30000, 4: 400000, 5: 600000, 6: 700000}

Ten en cuenta que el orden de los diccionarios en la lista influye, pues si hay claves repetidas, permanecerán los valores de aquellos diccionarios que se encuentren más a la derecha en la lista.

Recibe contenido exclusivo y obtén gratis la Hoja de Referencia de Python.

Antes de suscribirte consulta aquí la 
Información Básica sobre Protección de Datos. Responsable de datos: Juan Monroy Camafreita. Finalidad de recogida y tratamiento de datos personales: enviarte boletín informativo de Python y comunicaciones comerciales. Legitimación: tu consentimiento. Destinatarios: no se ceden a terceros. Los datos se almacenan en los servidores de marketing (MailRelay). Derechos: podrás ejercer tus derechos de acceso, rectificación, limitación y supresión de datos en info @ codigopiton.com así como presentar una reclamación ante una autoridad de control. Más información: política de privacidad, encontrarás información adicional sobre la recopilación y el uso de tu información personal.

Una variante sería utilizar la función reduce de la librería functools. reduce recibe una función f de dos parámetros y un iterable, que puede ser una lista. El funcionamiento es el siguiente: se aplica f a los dos primeros elementos del iterable y después se vuelve a aplicar con el resultado de la primera llamada y con el siguiente elemento del iterable. Se repite esto último hasta terminar con todos los elementos.

Versión con reduce:

import functools

union = functools.reduce(lambda a, b: a | b, diccionarios)

Desempaquetando con **. De la misma manera que antes, crearemos un diccionario vacío y después iremos desempaquetando en el bucle:

union = {}

for d in diccionarios:
    union = {**union, **d}

Y utilizando reduce quedaría de la siguiente manera:

union = functools.reduce(lambda a, b: {**a,  **b}, diccionarios)

Con la función update. Crearemos el primer diccionario vacío y después llamaremos a update en bucle con cada elemento de la lista:

union = {}

for d in diccionarios:
    union.update(d)

update es una función que muta el objeto y que no devuelve un nuevo diccionario. De esta manera, si queremos usar reduce tendremos que crear una función auxiliar que nos devuelva el diccionario después de llamar a update:

def unir_diccionarios(d1, d2):
    u = d1.copy()
    u.update(d2)
    return u

union = functools.reduce(lambda a, b: unir_diccionarios(a, b), diccionarios)

Por supuesto, podrás usar esta nueva función unir_diccionarios cuando te apetezca y no solo cuando necesites unir varios.

Vamos a ver una última opción un poco diferente a las que hemos visto hasta ahora, mediante el uso de la comprensión de diccionarios. Aunque su rendimiento es algo peor que usando copy y update, sigue siendo correcto:

union = {clave: valor for d in diccionarios for clave, valor in d.items()}

Conclusiones

Hemos aprendido diferentes maneras de unir dos diccionarios en Python, teniendo en cuenta la versión y considerando las claves repetidas: operador |, desempaquetado con ** y función update de la clase dict.

También hemos generalizado el problema para varios diccionarios.

Además, hemos visto una utilidad para la función reduce.

En tu mano queda estudiar el rendimiento de estas opciones. ¿Qué pasa cuando nuestros diccionarios son muy grandes? ¿Qué alternativa es mejor?

Cuando comprendas bien los métodos que en este artículo te he presentado puedes hacer el ejercicio de pensar cómo se harías si necesitaras combinar los valores de claves repetidas para no perder información. ¿Qué pasaría si tuviéramos diccionarios anidados?

Si te ha gustado el artículo considera suscribirte y te enviaré a tu correo La Hoja de Referencia de Python.

Otro artículo que puede resultar de tu interés es el siguiente: cómo comprobar si una clave existe en un diccionario.

¡Feliz programación!

 🎁 Tutorial Básico Interactivo y La Hoja de Referencia de Python – ¡Gratis!

La Hoja de Referencia de Python - Código Pitón
¿Quieres mejorar tu Python? Recibe totalmente gratis el Tutorial Básico Interactivo de Python, la Hoja de Referencia de Python y contenido exclusivo como trucos y consejos.



Antes de suscribirte consulta aquí la Información Básica sobre Protección de Datos. Responsable de los datos: Juan Monroy Camafreita. Finalidad de la recogida y tratamiento de los datos personales: enviarte boletín informativo de Python y comunicaciones comerciales. Legitimación: tu consentimiento. Destinatarios: no se ceden a terceros. Los datos se almacenan en los servidores de marketing (MailRelay). Derechos: podrás ejercer tus derechos de acceso, rectificación, limitación y supresión de datos en info @ codigopiton.com así como presentar una reclamación ante una autoridad de control. Más información en nuestra política de privacidad, encontrarás información adicional sobre la recopilación y el uso de tu información personal, incluida información sobre acceso, conservación, rectificación, eliminación, seguridad y otros temas.