Cómo fusionar dos diccionarios en Python 2 y 3

  1. Fusión de diccionarios en Python 2.7
  2. Método de fusión del diccionario de Python 3.5 (y superior)
  3. Fusión de métodos Conclusión

Supongamos que tenemos dos diccionarios A y B para ser fusionados, donde los valores en B reemplazarán a los valores en A si comparten la misma clave.

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

El objeto dictionary de Python tiene un método instrínseco update() para actualizar el diccionario A con el B,

A.update(B)

Pero los datos de A serán reemplazados en el lugar en lugar de devolver un nuevo diccionario que contenga la fusión de A y B.

Introduciremos los métodos de cómo fusionar dos diccionarios y devolver un nuevo diccionario.

Fusión de diccionarios en Python 2.7

Método de comprensión del diccionario - 1

C = {key: value for d in (A, B) for key, value in d.items()}

d.itmes() devuelve una lista de pares (clave, valor) como 2-tuplas del diccionario d.

Este método usa el anidado de comprensión de diccionario para fusionar dos diccionarios. Se debe prestar especial atención al orden correcto de for. Debería serlo,

flattern_patterns = [planet
                    for sublist in planets
                    for planet in sublist]

Método de comprensión del diccionario - 2

También podríamos usar el método dict() para inicializar el nuevo diccionario.

C = dict((key, value) for d in (A, B) for key, value in d.items())

Técnicamente hablando, es casi igual que el método anterior pero difiere en el rendimiento que se mencionará más adelante.

Método itertools.chain

El módulo herramientas estandariza un conjunto de bloques de construcción iterator. Tiene características como la rapidez y la eficiencia de la memoria.

itertools.chain devuelve un objeto chain cuyo método .next() devuelve elementos del primer iterable hasta que se agota, luego el/los siguiente(s) iterable(s), hasta que se agotan todos.

dict(itertools.chain(A.iteritems(), B.iteritems()))

iteritems() devuelve un iterador sobre los (key, value) elementos del diccionario.

Por lo tanto, los scripts anteriores devolverán un diccionario que contiene elementos de A y B.

Método copy y update

Como se mencionó al principio, update() podría fusionar A y B, pero reemplazará el diccionario que se encuentra en el lugar. Podríamos usar el método copy() para hacer una copia del diccionario A.

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

Análisis y comparación del rendimiento de los métodos de fusión

import timeit

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

TEST_CODE = '''
dict(itertools.chain(A.iteritems(), B.iteritems()))
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

SETUP_CODE = '''
def merge_dicts(a, b):
    m = a.copy()
    m.update(b)
    return m

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
merge_dicts(A, B)
'''
print min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000))

El resultado es

0.0162378
0.029774
0.019975
0.0110059
Método Rendimiento Rango
{key: value for d in (A, B) for key, value in d.items()} 0.0162378 2
dict((key, value) for d in (A, B) for key, value in d.items()) 0.029774 4
dict(itertools.chain(A.iteritems(), B.iteritems())) 0.019975 3
merge_dicts(a, b) 0.0110059 1

Método de fusión del diccionario de Python 3.5 (y superior)

Desde Python 3.5, además de los mismos métodos que en Python 2.7, tiene también el operador de desempaquetado ** de dictionary, tal y como se introdujo en PEP-448. Permite desempaquetar un número arbitrario de elementos.

Atención

d.iteritems() se vuelve obsoleto en Python 3. Ver PEP-469

>>> C = {**A, **B}
>>> C
{'x': 10, 'y': 30, 'z': 40}
import timeit

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}

SETUP_CODE = '''
A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
{**A, **B}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
{key: value for d in (A, B) for key, value in d.items()}
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
dict((key, value) for d in (A, B) for key, value in d.items())
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

TEST_CODE = '''
dict(itertools.chain(A.items(), B.items()))
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))

SETUP_CODE = '''
def merge_dicts(a, b):
    m = a.copy()
    m.update(b)
    return m

A = {'x': 10, 'y': 20}
B = {'y': 30, 'z': 40}
'''

TEST_CODE = '''
merge_dicts(A, B)
'''
print(min(timeit.repeat(setup = SETUP_CODE, stmt = TEST_CODE, repeat = 3, number=10000)))
0.0017047999999999508
0.009127499999999955
0.0168952
0.01078009999999996
0.005767999999999995
Método Rendimiento Rango
{**A, **B} 0.0017047999999999508 1
{key: value for d in (A, B) for key, value in d.items()} 0.009127499999999955 3
dict((key, value) for d in (A, B) for key, value in d.items()) 0.0168952 5
dict(itertools.chain(A.items(), B.items())) 0.01078009999999996 4
merge_dicts(a, b) 0.005767999999999995 2

Fusión de métodos Conclusión

En Python 2.7, copy y update es el mejor método.

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

En Python 3.5+, el método de desempaquetado del diccionario es el mejor.

{**A, **B}

Artículo relacionado - Python Dictionary

  • Cómo encontrar el valor máximo en el Diccionario Python
  • Cómo comprobar si existe una clave en un diccionario en Python