Come fondere due dizionari in Python 2 e 3

  1. Dizionario Python 2.7 Merge
  2. Python 3.5 (e oltre) Dizionario Metodo di fusione del dizionario
  3. Conclusione sui metodi di fusione

Supponiamo di avere due dizionari A e B da fondere, dove i valori in B sostituiranno i valori in A se condividono la stessa chiave.

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

L’oggetto dictionary di Python ha un metodo instrinseco update() metodo per aggiornare il dizionario A con B,

A.update(B)

Ma i dati di A saranno sostituiti sul posto invece di restituire un nuovo dizionario contenente la fusione di A e B.

Introdurremo i metodi per fondere due dizionari e restituire un nuovo dizionario.

Dizionario Python 2.7 Merge

Metodo di comprensione del dizionario - 1

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

d.itmes() restituisce una lista di coppie (key, value) come 2-tuple del dizionario d.

Questo metodo usa il nested dictionary comprehension per unire due dizionari. Il giusto ordine di for dovrebbe essere oggetto di una maggiore attenzione. Dovrebbe essere,

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

Metodo di comprensione del dizionario - 2

Potremmo anche usare il metodo dict() per inizializzare il nuovo dizionario.

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

Tecnicamente parlando, è quasi uguale al metodo di cui sopra, ma si differenzia per le prestazioni che saranno menzionate in seguito.

Metodo itertools.chain

Il modulo itertools standardizza un nucleo di blocchi di costruzione iterator. Ha caratteristiche come la velocità e l’efficienza della memoria.

itertools.chain restituisce un oggetto a catena il cui metodo .next() restituisce elementi dal primo iterabile fino all’esaurimento, poi il/i successivo/i iterabile/i, fino all’esaurimento di tutti.

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

iteritems() restituisce un iteratore sopra gli elementi (chiave, valore) del dizionario.

Pertanto, gli script sopra riportati restituiranno un dizionario contenente elementi di A e B.

Metodo copy e update

Come detto all’inizio, update() potrebbe fondere A e B, ma sostituirà il dizionario in-place. Potremmo usare il metodo copy() per fare una copia del dizionario A.

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

Unire i metodi Analisi delle prestazioni e confronto

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))

Il risultato è

0.0162378
0.029774
0.019975
0.0110059
Metodo Prestazioni Classifica
{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

Python 3.5 (e oltre) Dizionario Metodo di fusione del dizionario

Da Python 3.5, oltre agli stessi metodi di Python 2.7, ha anche l’operatore di “disimballaggio” del “contraddittorio”, come introdotto in PEP-448. Esso permette di spacchettare un numero arbitrario di elementi.

Attenzione

d.iteritems() diventa deprecato in Python 3. Vedere 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
Metodo Prestazioni Classifica
{**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

Conclusione sui metodi di fusione

In Python 2.7, copy e update è il metodo migliore.

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

In Python 3.5+, il metodo di disimballaggio del dizionario è il migliore.

{**A, **B}

Articolo correlato - Python Dictionary

  • Somma dei valori del dizionario in Python