Am două Python dicționare, și vreau să scriu o singură expresie care returnează aceste două dicționare, au fuzionat. Actualizare()` metoda ar fi ceea ce am nevoie, dacă s-a întors rezultatul său în loc de a modifica un dict în loc.
>>> x = {'a': 1, 'b': 2}
>>> y = {'b': 10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}
Cum pot obține finală a fuzionat dict în "z", nu cu "x"?
(Pentru a fi extra-clară, ultima-o câștigă conflict-manipularea de dict.update()
este ceea ce am'm în căutarea la fel de bine.)
Cum pot fuziona două Python dicționare într-o singură expresie?
Pentru dicționare " x " și "y", " z "devine un superficial fuzionat dicționar cu valori de la" y "înlocuirea celor de la "x".
- În Python 3.5 sau mai mare:
z = {**x, **y}
z = merge_two_dicts(x, y)
Spune că ai două dicts și vrei să le contopească într-o nouă dict fără a modifica originalul dicts:
x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
Rezultatul dorit este de a obține un nou dicționar ("z"), cu valori fuzionat, și cel de-al doilea dict's valorile suprascrierea celor din prima.
>>> z
{'a': 1, 'b': 3, 'c': 4}
O nouă sintaxă pentru acest lucru, a propus în PEP 448 și disponibil din Piton de 3,5, este z = {x y} Și este într-adevăr o singură expresie. Rețineți că putem merge cu literală notație precum:
z = {**x, 'foo': 1, 'bar': 2, **y}
și acum:
>>> z
{'a': 1, 'b': 3, 'foo': 1, 'bar': 2, 'c': 4}
Este acum arată ca în aplicare în programul de lansare pentru 3.5, PEP 478, și a făcut drumul său în ceea Ce's New in Python 3.5 document. Cu toate acestea, deoarece multe organizații sunt încă pe Python 2, ați putea dori pentru a face acest lucru într-un compatibil drum. Clasic Pythonic fel, disponibil în Python 2 și Python 3.0-3.4, este de a face acest lucru ca pe un proces în două etape:
z = x.copy()
z.update(y) # which returns None since it mutates z
În ambele abordări, " y "va veni a doua și a valorilor sale va înlocui" x "'s valori, astfel 'b'
va indica " 3 " în rezultatul final.
Dacă nu sunteți încă pe Python 3.5, sau nevoie pentru a scrie compatibil cod, și doriți acest lucru într-un singur exprimare, cele mai performante în timp ce abordarea corectă este să-l pună într-o funcție:
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
și atunci aveți o singură expresie: z = merge_two_dicts(x, y) Puteți face, de asemenea, o funcție pentru a fuziona un număr nedefinit de previziuni, de la zero la un număr foarte mare:
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
Această funcție va funcționa în Python 2 și 3 pentru toți dicts. de exemplu, dat dicts " a " la "g":
z = merge_dicts(a, b, c, d, e, f, g)
și perechi de valori-cheie în " g "va avea prioritate față dicts" a " la "f", și așa mai departe.
Don't folosi ceea ce vezi în fosta acceptat răspunsul:
z = dict(x.items() + y.items())
În Python 2, creați două liste în memorie pentru fiecare dict, de a crea o a treia listă în memorie cu o lungime egală cu lungimea de primele două puse împreună, și apoi aruncați toate cele trei liste pentru a crea dict. În Python 3, aceasta va eșua pentru că're adăugarea a două dict_items
obiecte împreună, nu două liste -
>>> 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'
și tu ar trebui să în mod explicit crea liste, de exemplu, z = dict(lista(x.elemente()) + lista(y.elemente())). Aceasta este o risipă de resurse și putere de calcul. În mod similar, uniunea de elemente()
în Python 3 (viewitems()
în Python 2.7) va eșua, de asemenea, atunci când valorile sunt unhashable obiecte (cum ar fi liste, de exemplu). Chiar dacă valorile sunt hashable, din seturi sunt semantic neordonate, comportamentul este definit în ceea ce privește prioritate. Deci, don't face acest lucru:
>>> c = dict(a.items() | b.items())
Acest exemplu demonstrează ce se întâmplă atunci când valorile sunt 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'
Aici's un exemplu în care y ar trebui să aibă prioritate, dar în loc de valoarea din x este păstrat datorită ordine arbitrară de seturi:
>>> x = {'a': 2}
>>> y = {'a': 1}
>>> dict(x.items() | y.items())
{'a': 2}
Un alt hack tu nu trebuie să utilizeze:
z = dict(x, **y)
Aceasta folosește dict` constructor, și este foarte rapid și eficient memoria (chiar puțin mai mult decât noastră proces în două etape), dar dacă nu știi exact ce se întâmplă aici (care este, cea de-a doua dict este trecut ca și cuvinte cheie argumente dict constructor), l's greu de citit, l's nu destinate utilizării, și deci nu este Pythonic. Aici's un exemplu de utilizare fiind reabilitate în django. Dicts sunt destinate pentru a lua hashable chei (de exemplu, frozensets sau tupluri), dar această metodă eșuează în Python 3 atunci când tastele nu sunt siruri de caractere.
>>> c = dict(a, **b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings
De mailing list, Guido van Rossum, creator de limba, a scris:
nu am nimic cu declararea dict({}, **{1:3}) ilegal, deoarece, după toate, este abuz de
- mecanism. și se Pare că dict(x, y) este de a merge în jurul valorii de ca "cool hack" pentru "apel x.update(y) și a reveni x". Personal, mi se pare mai demn de dispreț decât rece. Aceasta este înțelegerea mea (precum și înțelegerea creator de limba) care utilizarea acestora pentru `dict(y)` este pentru crearea de previziuni pentru lizibilitate scopuri, de exemplu:
dict(a=1, b=10, c=11)
în loc de
{'a': 1, 'b': 10, 'c': 11}
în Ciuda a ceea ce spune Guido,
dict(x, **y)
este în conformitate cu dict caietul de sarcini, care btw. funcționează atât pentru Python 2 și 3. Faptul că acest lucru funcționează doar pentru chei string este o consecință directă a modului de cuvinte cheie parametrii de lucru și nu un scurt-apropie de dict. Nici nu este folosind operatorul în acest loc un abuz de mecanism, în fapt a fost conceput tocmai pentru a trece dicts ca și cuvinte cheie. Din nou, nu't de lucru pentru 3 atunci când tastele sunt non-siruri de caractere. Implicit asteptare contract este faptul că spațiile de nume ia ordinare dicts, în timp ce utilizatorii trebuie să treacă doar de cuvinte cheie argumente care sunt siruri de caractere. Toate celelalte callables aplicat-o.dict
a rupt această coerență în 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}
Această inconsecvență a fost rău dat alte implementări de Python (Pypy, Jython, IronPython). Astfel, a fost stabilit în Python 3, ca această utilizare ar putea fi o rupere de schimbare. Îndrăznesc să afirm că este rău intenționat incompetentă a intenționat să scrie cod care funcționează doar într-o versiune de o limbă sau care funcționează numai anumite constrângeri arbitrare. Mai multe comentarii:
dict(x.elemente() + y.elemente())
este în continuare cel mai citit soluție pentru Python 2. Lizibilitatea contează. Răspunsul meu:merge_two_dicts(x, y)
de fapt se pare mult mai clare pentru mine, dacă am're de fapt preocupat de lizibilitate. Și nu este compatibil, ca Python 2 este din ce în ce mai depreciată.{**x **y}
nu pare să se ocupe imbricate dicționare. conținutul imbricate cheile sunt suprascrise, nu comasate [...] am ajuns sa fiu ars de aceste răspunsuri, care nu merge recursiv și am fost surprins ca nimeni nu a pomenit de asta. În interpretarea mea de cuvântul "unirea" aceste răspunsuri descrie "actualizarea una dict cu un alt", și nu fuzionează. Da. Trebuie să consultați înapoi la întrebarea, care este de a cere un superficial merge de doi dicționare, cu prima's, valorile fiind suprascrise de cea de-a doua's, într - o singură expresie. Presupunând că doi dicționar de dicționare, s-ar putea recursiv a le îmbina într-o singură funcție, dar ar trebui să fie atenți să nu pentru a modifica dicts fie de la sursă, și cea mai sigură cale de a evita asta este sa faci o copie, atunci când atribuirea de valori. Ca și tastele trebuie să fie hashable și sunt, de obicei, prin urmare, imuabil, este inutil să copiați-le:
from copy import deepcopy
def dict_of_dicts_merge(x, y):
z = {}
overlapping_keys = x.keys() & y.keys()
for key in overlapping_keys:
z[key] = dict_of_dicts_merge(x[key], y[key])
for key in x.keys() - overlapping_keys:
z[key] = deepcopy(x[key])
for key in y.keys() - overlapping_keys:
z[key] = deepcopy(y[key])
return z
Utilizare:
>>> x = {'a':{1:{}}, 'b': {2:{}}}
>>> y = {'b':{10:{}}, 'c': {11:{}}}
>>> dict_of_dicts_merge(x, y)
{'b': {2: {}, 10: {}}, 'a': {1: {}}, 'c': {11: {}}}
Vine cu situații neprevăzute pentru alte tipuri de valoare este mult dincolo de domeniul de aplicare de această întrebare, așa că am vă va indica la răspunsul meu la canonice întrebare pe un "Dicționare dicționare merge".
Aceste abordări sunt mai puțin performante, dar ei vă va oferi un comportament corect. Ei vor fi mult mai puțin performante decât "copie" și "actualizare" sau noul despachetarea pentru că parcurge fiecare pereche de chei-valoare la un nivel superior de abstractizare, dar nu* să respecte ordinea de prioritate (acesta dicts au prioritate) Puteți, de asemenea, lanțul de dicts manual în interiorul unui dict de înțelegere:
{k: v for d in dicts for k, v in d.items()} # iteritems in Python 2.7
sau în python 2.6 (și, probabil, cât mai devreme 2.4 atunci când generatorul de expresii au fost introduse):
dict((k, v) for d in dicts for k, v in d.items())
`itertools.lanțul va lanț iteratori peste perechi cheie-valoare, în ordinea corectă:
import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))
Am'm doar de gând să facă performanță analiza uzanțele cunoscut să se comporte corect.
import timeit
Următoarele se face pe Ubuntu 14.04 În Python 2.7 (sistem 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
În 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
În cazul tău, ce poți să faci este:
z = dict(x.items() + y.items())
Acest lucru va fi, după cum doriți, pune finală dict în "z", și de a face valoare pentru cheia b
fie corect înlocuită de cea de-a doua ("y") dict's valoare:
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}
Dacă utilizați Python 3, acesta este doar un pic mai complicat. Pentru a crea "z":
>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
Un alt, mult mai concis, opțiunea:
z = dict(x, **y)
Notă: acest lucru a devenit un popular răspuns, dar este important să subliniez că, dacă " y " a orice non-string chei, faptul că aceasta funcționează la toate este un abuz de o CPython implementarea detaliu, și nu de muncă în Python 3, sau în PyPy, IronPython, sau Jython. De asemenea, Guido nu este un fan. Deci nu pot't recomanda aceasta tehnica de transmite-compatibil sau cross-implementarea cod portabil, ceea ce înseamnă că ar trebui să fie evitate în totalitate.
Acest lucru, probabil, a câștigat't fi un răspuns mai populare, dar aproape sigur nu vrei să faci asta. Dacă doriți o copie care's o îmbinare, apoi utilizați copia (sau deepcopy, în funcție de ceea ce vrei) si apoi update. Cele două linii de cod sunt mult mai ușor de citit - mai Pythonic - decât o singură linie cu crearea .elemente() + .elemente(). Explicită este mai bună decât implicit.
În plus, atunci când utilizați .elemente() (pre Python 3.0), nu're a crea o nouă listă care conține elemente din dict. Dacă dicționare sunt mari, atunci este destul de o mulțime de cheltuieli de regie (două liste mari care vor fi aruncate imediat ce a fuzionat dict este creat). update() pot lucra mai eficient, deoarece acesta poate rula prin cel de-al doilea dict element cu element.
În ceea ce privește timp:
>>> 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
OMI mici încetinire dintre primele două este în valoare de ea pentru lizibilitate. În plus, cuvinte cheie argumente pentru crearea dicționarul a fost adăugat numai în Python 2.3, întrucât copia() și update() va funcționa în versiuni mai vechi.
Într-un follow-up raspuns, m-ai întrebat despre performanța relativă a acestor două alternative:
z1 = dict(x.items() + y.items())
z2 = dict(x, **y)
Pe masina mea, cel puțin (o destul de obișnuit x86_64 funcționare Python 2.5.2), alternative z2
nu este doar mai scurte și mai simple, dar, de asemenea, semnificativ mai repede. Puteți verifica acest lucru pentru tine, folosind `datănu modulul care vine cu Python.
Exemplu 1: identic dicționare de cartografiere 20 de numere întregi consecutive la sine:
% 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
z2
pune de un factor de 3,5 sau cam asa ceva. Dicționare diferite par să cedeze destul de diferite rezultate, dar z2
întotdeauna pare să iasă în față. (Dacă veți obține rezultate inconsistente pentru acelasi test, încercați trecerea la -r
, cu un număr mai mare decât cel implicit 3.)
Exemplul 2: non-se suprapun dicționare de cartografiere 252 scurt șiruri de numere întregi și 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
câștigă cu aproximativ un factor de 10. Ca's o victorie destul de mare în cartea mea!
După compararea celor două, m-am întrebat dacă z1
's performanța slabă ar putea fi atribuite la cheltuielile de construire a două liste de elemente, care la rândul său m-a determinat să mă întreb dacă această variație s-ar putea lucra mai bine:
from itertools import chain
z3 = dict(chain(x.iteritems(), y.iteritems()))
Câteva teste rapide, de exemplu
% 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
mă duc la concluzia că z3
este oarecum mai rapid decât z1
, dar nu aproape la fel de repede ca z2
. Cu siguranta nu merita toate tastarea suplimentare.
Această discuție este încă lipsește ceva important, care este o comparație de performanță dintre aceste alternative cu "evident" modul de a fuziona două liste: folosind "actualizare" metoda. Să încercați să păstrați lucrurile pe picior de egalitate cu expresii, dintre care niciunul nu modifica x sau y, am'm de gând să facă o copie de x în loc de a modifica în loc, după cum urmează:
z0 = dict(x)
z0.update(y)
Un rezultat tipic:
% 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
Cu alte cuvinte, z0
și z2
pare să aibă, în esență, identice performanță. Crezi că acest lucru ar putea fi o coincidență? Eu nu't....
De fapt, am'd merge atât de departe încât să pretindă că-l's imposibil pentru Python pur cod pentru a face orice mai bine decât asta. Și dacă poți să faci în mod semnificativ mai bine într-un C modul de extensie, îmi imaginez Python oameni ar putea fi interesat în a încorpora cod (sau o variație pe abordarea ta) în Python core. Python folosește dict
într-o mulțime de locuri; optimizarea operațiunilor sale este o afacere mare.
Ai putea scrie, de asemenea, acest lucru ca
z0 = x.copy()
z0.update(y)
ca Tony are, dar (nu este surprinzator) diferența în notație se dovedește a nu avea nici un efect măsurabil asupra performanței. Utilizați oricare dintre acestea se pare corect pentru tine. Desigur, el's absolut corect să subliniez că cele două-declarație versiune este mult mai ușor de înțeles.
Am vrut ceva similar, dar cu capacitatea de a specifica modul în care valorile de pe chei duplicat au fost comasate, așa că am intrat asta (dar nu foarte mult testa). Evident, acest lucru nu este o singură expresie, dar este un singur apel de funcție.
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
În Python 3.0 și mai târziu, puteți utiliza colecții.ChainMap care grupează mai multe previziuni sau alte mapări împreună pentru a crea un unic, actualizabile vedere:
>>> 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
Actualizare pentru Piton de 3,5 și mai târziu: puteți utiliza PEP 448 dicționar extins de ambalare și despachetare. Acest lucru este rapid și ușor:
>>> x = {'a':1, 'b': 2}
>>> y = y = {'b':10, 'c': 11}
>>> {**x, **y}
{'a': 1, 'b': 10, 'c': 11}
Demonstrație:def deepupdate(original, actualizare): """ Recursiv actualizarea unui dict. Subdict's câștigat't fi suprascrise, dar, de asemenea, actualizate. """ pentru cheie, valoare în original.iteritems(): dacă cheia nu în update: update[cheie] = valoare elif isinstance(valoare, dict): deepupdate(valoare, actualizare[cheie]) reveni actualizare
Ieșiri:pluto_original = { 'numele': 'Pluto', 'detalii': { 'coada': Adevărat, 'de culoare': 'orange' } } pluto_update = { 'numele': 'Pluutoo', 'detalii': { 'de culoare': 'albastru' } }
imprimare deepupdate(pluto_original, pluto_update)
Multumesc rednaw pentru modificări.{ 'numele': 'Pluutoo', 'detalii': { 'de culoare': 'albastru', 'coada': Adevărat } }
Cea mai bună versiune m-am putut gândi în timp ce nu utilizați copia ar fi:
from itertools import chain
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
dict(chain(x.iteritems(), y.iteritems()))
L's mai rapid decât dict(x.elemente() + y.elemente())
dar nu la fel de repede ca n = copie(o); n.actualizare(b), cel puțin pe CPython. Această versiune, de asemenea, funcționează în Python 3, dacă vă schimbați
iteritems () " la " elementele()`, care se face automat de către 2to3 instrument.
Personal, îmi place această versiune mai bune pentru ca descrie destul de bine ceea ce vreau într-un singur funcționale sintaxă. Singura mică problemă este că nu't face absolut evident că valorile y are prioritate față de valorile de la x, dar nu't crede's greu să-mi dau seama.
În timp ce întrebarea a fost deja a răspuns de mai multe ori, această soluție simplă la această problemă nu a fost publicat încă.
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z4 = {}
z4.update(x)
z4.update(y)
Este la fel de rapid ca z0 și răul z2 menționate mai sus, dar ușor de înțeles și de a schimba.
def dict_merge(a, b):
c = a.copy()
c.update(b)
return c
new = dict_merge(old, extras)
Printre astfel de dubios și dubioase răspunsuri, acest exemplu este unul și numai bun mod de a merge dicts în Python, aprobat de către dictator pe viață Guido van Rossum el! Altcineva a sugerat jumătate de asta, dar nu l-am pus într-o funcție.
print dict_merge(
{'color':'red', 'model':'Mini'},
{'model':'Ferrari', 'owner':'Carl'})
oferă:
{'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'}
Daca tu crezi lambda sunt rele, apoi citiți mai departe. Așa cum a solicitat, puteți scrie rapid și memorie-soluție eficientă cu o singură expresie:
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}
Cum a sugerat mai sus, cu ajutorul a două linii sau a scrie o funcție este, probabil, o modalitate mai bună de a merge.
Fi pythonic. Utilizați un înțelegerea:
z={i:d[i] for d in [x,y] for i in d}
>>> print z
{'a': 1, 'c': 11, 'b': 10}
În python3, la produse
metoda nu se mai returnează o listă, ci mai degrabă o vedere, care acționează ca un set. În acest caz,'ll nevoie pentru a lua set uniunii din concatenarea cu " + " a câștigat't de lucru:
dict(x.items() | y.items())
Pentru python3 comportament în versiunea 2.7, viewitems
metodă ar trebui să funcționeze în loc de "articol":
dict(x.viewitems() | y.viewitems())
Eu prefer această notație oricum, deoarece se pare mai natural să cred că de ea ca un set uniunii funcționare, mai degrabă decât de concatenare (ca titlu spectacole).
Edit:
Un cuplu mai multe puncte pentru python 3. În primul rând, rețineți că dict(x, **y)
truc câștigat't de muncă în python 3 cu excepția cazului în care cheile în " y " sunt siruri de caractere.
De asemenea, Raymond Hettinger's Chainmap răspunde este destul de elegant, deoarece aceasta poate avea un număr arbitrar de dicts ca argumente, dar de la docs se pare că secvențial arată o listă cu toate dicts pentru fiecare căutare:
Căutări de căutare stau la baza asocierilor succesiv, până când o cheie este găsit.
Acest lucru poate încetini, dacă aveți o mulțime de căutări în cererea dumneavoastră:
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
Deci, aproximativ un ordin de mărime mai lent pentru căutări. Am'm un fan al Chainmap, dar pare mai puțin practice unde pot exista mai multe căutări.
Abuzul duce la o singură expresie soluție pentru Matei's a răspunde:
>>> 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}
Ai spus că ai vrut o expresie, asa ca am abuzat de "lambda" pentru a lega un nume, și tupluri pentru a trece peste lambda's o expresie limită. Simțiți-vă liber să mă ascund.
Ai putea, de asemenea, face acest lucru, desigur, dacă nu't grijă despre copierea:
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (x.update(y), x)[1]
>>> z
{'a': 1, 'b': 10, 'c': 11}
Două dicționare
def union2(dict1, dict2):
return dict(list(dict1.items()) + list(dict2.items()))
n dicționare
def union(*dicts):
return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))
"sum" are rău de performanță. Vezi https://mathieularose.com/how-not-to-flatten-a-list-of-lists-in-python/
Soluție simplă, folosind itertools care păstrează ordinea (din urmă dicts au prioritate)
import itertools as it
merge = lambda *args: dict(it.chain.from_iterable(it.imap(dict.iteritems, args)))
Și-l's utilizare:
>>> 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}