python - एक अभिव्यक्ति में दो शब्दकोशों को कैसे विलय करें?




dictionary merge (20)

मैं एक ही अभिव्यक्ति में दो पायथन शब्दकोश कैसे विलय कर सकता हूं?

x और y , z x से मूल्यों के साथ y साथ एक उथले विलय वाले शब्दकोश बन जाता है।

  • पायथन 3.5 या उससे अधिक में:

    z = {**x, **y}
    w = {'foo': 'bar', 'baz': 'qux', **y}  # merge a dict with literal values
    
  • पायथन 2 में, (या 3.4 या निचला) एक फ़ंक्शन लिखें:

    def merge_two_dicts(x, y):
        z = x.copy()   # start with x's keys and values
        z.update(y)    # modifies z with y's keys and values & returns None
        return z
    

    और अब:

    z = merge_two_dicts(x, y)
    

व्याख्या

मान लें कि आपके पास दो डिक्ट्स हैं और आप मूल डिक्ट्स को बदलने के बिना उन्हें नए नियम में विलय करना चाहते हैं:

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}

वांछित परिणाम वैल्यू के साथ एक नया शब्दकोश ( z ) प्राप्त करना है, और दूसरे नियमों के मान पहले से ओवरराइट करना है।

>>> z
{'a': 1, 'b': 3, 'c': 4}

इसके लिए एक नया वाक्यविन्यास, पीईपी 448 में प्रस्तावित और पायथन 3.5 के रूप में उपलब्ध है

z = {**x, **y}

और यह वास्तव में एक अभिव्यक्ति है।

ध्यान दें कि हम शाब्दिक नोटेशन के साथ भी विलय कर सकते हैं:

z = x.copy()
z.update(y) # which returns None since it mutates z

और अब:

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

अब यह 3.5, पीईपी 478 के रिलीज शेड्यूल में लागू किया जा रहा है, और अब यह पायथन 3.5 दस्तावेज़ में व्हाट्स न्यू में अपना रास्ता बना दिया है।

हालांकि, चूंकि कई संगठन अभी भी पायथन 2 पर हैं, इसलिए आप इसे पीछे के संगत तरीके से करना चाहेंगे। पाइथन 2 और पायथन 3.0-3.4 में उपलब्ध शास्त्रीय पायथनिक तरीका, इसे दो-चरणीय प्रक्रिया के रूप में करना है:

z = merge_two_dicts(x, y)

दोनों दृष्टिकोणों में, y दूसरा आ जाएगा और इसके मान x मानों को प्रतिस्थापित करेंगे, इस प्रकार 'b' हमारे अंतिम परिणाम में 3 इंगित करेगा।

अभी तक पायथन 3.5 पर नहीं, लेकिन एक अभिव्यक्ति चाहते हैं

यदि आप अभी तक पायथन 3.5 पर नहीं हैं, या पिछड़े-संगत कोड लिखने की आवश्यकता है, और आप इसे एक अभिव्यक्ति में चाहते हैं, तो सही प्रदर्शन करते समय सबसे अधिक प्रदर्शनकर्ता इसे एक फ़ंक्शन में रखना है:

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

और फिर आपके पास एक अभिव्यक्ति है:

z = merge_dicts(a, b, c, d, e, f, g) 

आप शून्य से एक बहुत बड़ी संख्या में, एक अपरिभाषित संख्या में विलयों को मर्ज करने के लिए एक फ़ंक्शन भी बना सकते हैं:

z = dict(x.items() + y.items())

यह फ़ंक्शन सभी डिक्ट्स के लिए पायथन 2 और 3 में काम करेगा। उदाहरण के लिए a g को दिया गया है:

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

और g में महत्वपूर्ण मूल्य जोड़े को डिक्ट्स पर a से अधिक प्राथमिकता लेनी होगी, और इसी तरह।

अन्य उत्तरों की आलोचनाएं

पूर्व में स्वीकृत उत्तर में जो भी आप देखते हैं उसका उपयोग न करें:

>>> c = dict(a.items() | b.items())

पायथन 2 में, आप प्रत्येक निर्देश के लिए स्मृति में दो सूचियां बनाते हैं, स्मृति में तीसरी सूची बनाते हैं, जिसमें पहले दो की लंबाई के बराबर लंबाई होती है, और फिर सभी तीन सूचियों को निर्देश बनाने के लिए छोड़ दें। पायथन 3 में, यह असफल हो जाएगा क्योंकि आप दो dict_items ऑब्जेक्ट्स को एक साथ जोड़ रहे हैं, दो सूचियां नहीं -

>>> x = {'a': []}
>>> y = {'b': []}
>>> dict(x.items() | y.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

और आपको उन्हें सूचियों के रूप में स्पष्ट रूप से बनाना होगा, उदाहरण के लिए z = dict(list(x.items()) + list(y.items())) । यह संसाधनों और गणना शक्ति का अपशिष्ट है।

इसी प्रकार, पाइथन 3 (पायथन 2.7 items() में पायथन 3 ( viewitems() items() में items() संघ लेना भी असफल होगा जब मूल्य अस्थिर वस्तुओं (जैसे सूचियों, उदाहरण के लिए) हैं। यहां तक ​​कि यदि आपके मान हैंशबल हैं, चूंकि सेट अर्थात् अनियंत्रित हैं, इसलिए व्यवहार को प्राथमिकता के संबंध में अपरिभाषित किया गया है। तो ऐसा मत करो:

>>> x = {'a': 2}
>>> y = {'a': 1}
>>> dict(x.items() | y.items())
{'a': 2}

यह उदाहरण दर्शाता है कि क्या होता है जब मूल्य अचूक होते हैं:

z = dict(x, **y)

यहां एक उदाहरण दिया गया है जहां y को प्राथमिकता होनी चाहिए, लेकिन सेट के मनमानी क्रम के कारण x से मान को बनाए रखा गया है:

>>> c = dict(a, **b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

एक और हैक जिसका आप उपयोग नहीं करना चाहिए:

dict(a=1, b=10, c=11)

यह dict कन्स्ट्रक्टर का उपयोग करता है, और यह बहुत तेज़ और मेमोरी कुशल है (यहां तक ​​कि हमारी दो-चरणीय प्रक्रिया की तुलना में थोड़ा और भी) लेकिन जब तक आप यह नहीं जानते कि यहां क्या हो रहा है (यानी, दूसरा नियम कीवर्ड तर्क के रूप में पारित किया जा रहा है ताना कन्स्ट्रक्टर), पढ़ना मुश्किल है, यह इच्छित उपयोग नहीं है, और इसलिए यह पाइथोनिक नहीं है।

Django में उपचार के उपयोग का एक उदाहरण यहां दिया गया है।

डिक्ट्स का उद्देश्य हैशबल कुंजियां (जैसे फ्रोजनसेट या टुपल्स) लेना है, लेकिन यह विधि पायथन 3 में विफल होती है जब चाबियाँ स्ट्रिंग नहीं होती हैं।

{'a': 1, 'b': 10, 'c': 11}

मेलिंग सूची से , भाषा के निर्माता ग्विडो वैन रॉसम ने लिखा:

मैं dict ({}, ** {1: 3}) घोषित करने के साथ ठीक हूं, क्योंकि आखिरकार यह ** तंत्र का दुरुपयोग है।

तथा

स्पष्ट रूप से dict (x, ** y) "कॉल x.update (y) के लिए" कूल हैक "के रूप में चारों ओर जा रहा है और x वापस लौटा रहा है"। व्यक्तिगत रूप से मुझे इसे ठंडा से अधिक घृणित लगता है।

यह मेरी समझ है (साथ ही भाषा के निर्माता की समझ) कि dict(**y) लिए इच्छित उपयोग पठनीयता उद्देश्यों के लिए चित्र बनाने के लिए है, उदाहरण के लिए:

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

के बजाय

{k: v for d in dicts for k, v in d.items()} # iteritems in Python 2.7

टिप्पणियों का जवाब

Guido क्या कहता है के बावजूद, dict(x, **y) dict विनिर्देश के अनुरूप है, जो btw। पाइथन 2 और 3 दोनों के लिए काम करता है। तथ्य यह है कि यह केवल स्ट्रिंग कुंजियों के लिए काम करता है, इसका मुख्य परिणाम यह है कि कीवर्ड पैरामीटर कैसे काम करते हैं और न ही कमांड की कमी करते हैं। न ही इस स्थान पर ** ऑपरेटर का उपयोग तंत्र के दुरुपयोग का उपयोग कर रहा है, वास्तव में ** कीवर्ड को कीवर्ड के रूप में सटीक रूप से पास करने के लिए डिज़ाइन किया गया था।

फिर, यह 3 के लिए काम नहीं करता है जब चाबियाँ गैर-तार होती हैं। निहित कॉलिंग अनुबंध यह है कि नेमस्पेस सामान्य डिक्ट्स लेते हैं, जबकि उपयोगकर्ताओं को केवल कीवर्ड तर्कों को पार करना होगा जो तार हैं। अन्य सभी कॉलबल्स ने इसे लागू किया। पायथन 2 में इस स्थिरता को तोड़ दिया:

dict((k, v) for d in dicts for k, v in d.items())

पाइथन (पायपी, ज्योथन, आयरनपीथन) के अन्य कार्यान्वयन के कारण यह असंगतता खराब थी। इस प्रकार यह पायथन 3 में तय किया गया था, क्योंकि यह उपयोग एक तोड़ने वाला परिवर्तन हो सकता है।

मैं आपको प्रस्तुत करता हूं कि जानबूझकर कोड लिखने के लिए दुर्भावनापूर्ण अक्षमता है जो केवल एक भाषा के एक संस्करण में काम करती है या केवल कुछ मनमानी बाधाओं को ही काम करती है।

अधिक टिप्पणियां:

dict(x.items() + y.items()) अभी भी पायथन 2 के लिए सबसे अधिक पढ़ने योग्य समाधान है। पठनीयता की गणना करता है।

मेरी प्रतिक्रिया: merge_two_dicts(x, y) वास्तव में मेरे लिए बहुत स्पष्ट लगता है, अगर हम वास्तव में पठनीयता के बारे में चिंतित हैं। और यह आगे संगत नहीं है, क्योंकि पाइथन 2 को तेजी से बहिष्कृत किया जा रहा है।

{**x, **y} नेस्टेड शब्दकोशों को संभालने में प्रतीत नहीं होता है। घोंसले की चाबियों की सामग्री को आसानी से अधिलेखित किया जाता है, विलय नहीं किया जाता है [...] मैं इन उत्तरों से जला दिया जाता है जो पुनरावर्ती रूप से विलय नहीं करते हैं और मुझे आश्चर्य हुआ कि किसी ने इसका उल्लेख नहीं किया। "विलय" शब्द की मेरी व्याख्या में इन उत्तरों का वर्णन "एक दूसरे के साथ एक निर्देश को अद्यतन करना" और विलय नहीं करना है।

हाँ। मुझे आपको एक प्रश्न में वापस संदर्भित करना होगा, जो दो शब्दकोशों के उथले विलय के लिए पूछ रहा है, जिसमें पहले के मूल्य दूसरे के द्वारा अधिलेखित किए जा रहे हैं - एक अभिव्यक्ति में।

शब्दकोशों के दो शब्दकोशों को मानते हुए, कोई भी उन्हें एक ही फ़ंक्शन में विलय कर सकता है, लेकिन आपको सावधान रहना चाहिए कि किसी भी स्रोत से डिक्ट्स को संशोधित न करें, और इससे बचने का सबसे अच्छा तरीका मूल्यों को निर्दिष्ट करते समय प्रतिलिपि बनाना है। चूंकि चाबियाँ हर्षनीय होनी चाहिए और आमतौर पर इसलिए अपरिवर्तनीय होती हैं, इसलिए उन्हें प्रतिलिपि बनाना व्यर्थ है:

import itertools
z = dict(itertools.chain(x.iteritems(), y.iteritems()))

उपयोग:

import timeit

अन्य मूल्य प्रकारों के लिए आकस्मिकताओं के साथ आने से इस प्रश्न के दायरे से बहुत दूर है, इसलिए मैं आपको "शब्दकोश विलय के शब्दकोश" पर कैननिकल प्रश्न के उत्तर में बताऊंगा ।

कम प्रदर्शन करने वाला लेकिन सही विज्ञापन-दस्तावेज़

ये दृष्टिकोण कम प्रदर्शनकारी हैं, लेकिन वे सही व्यवहार प्रदान करेंगे। वे copy और update या नई अनपॅकिंग की तुलना में बहुत कम प्रदर्शन करेंगे क्योंकि वे प्रत्येक कुंजी-मूल्य जोड़ी के माध्यम से उच्च स्तर पर अमूर्तता के माध्यम से पुनरावृत्त होते हैं, लेकिन वे प्राथमिकता के क्रम का सम्मान करते हैं (बाद के डिकट्स की प्राथमिकता है)

आप एक धैर्य समझ के अंदर मैन्युअल रूप से चित्रों को भी चेन कर सकते हैं:

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

या पायथन 2.6 में (और शायद जेनरेटर अभिव्यक्तियों को पेश किए जाने पर 2.4 के रूप में):

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

itertools.chain सही क्रम में कुंजी-मूल्य जोड़े पर इटरेटर को चेन करेगा:

z = dict(x.items() + y.items())

क्षमता का परिक्षण

मैं केवल सही व्यवहार करने के लिए जाने वाले उपयोगों के प्रदर्शन विश्लेषण करने जा रहा हूं।

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}

निम्नलिखित उबंटू 14.04 पर किया जाता है

पायथन 2.7 (सिस्टम पायथन) में:

>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}

पायथन 3.5 में (deadsnakes पीपीए):

z = x.copy()
z.update(y)

शब्दकोश पर संसाधन

https://code.i-harness.com

मेरे पास दो पायथन शब्दकोश हैं, और मैं एक एकल अभिव्यक्ति लिखना चाहता हूं जो इन दो शब्दकोशों को लौटाता है, विलय हो जाता है। update() विधि की आवश्यकता होगी जो मुझे चाहिए, अगर यह एक जगह में एक नियम को संशोधित करने के बजाय अपना परिणाम लौटाता है।

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print(z)
None
>>> x
{'a': 1, 'b': 10, 'c': 11}

मैं z में अंतिम विलयित आदेश कैसे प्राप्त कर सकता हूं, x नहीं?

(अतिरिक्त स्पष्ट होने के लिए, dict.update() की अंतिम-एक-जीत संघर्ष-हैंडलिंग मैं भी ढूंढ रहा हूं।)


एक धैर्य को दोबारा अद्यतन / गहरा अद्यतन करें

x = {'a': 1, 'b': 1}
y = {'a': 2, 'c': 2}
final = {**x, **y} 
final
# {'a': 2, 'b': 1, 'c': 2}

प्रदर्शन:

final = {'a': 1, 'b': 1, **x, **y}

आउटपुट:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

संपादन के लिए धन्यवाद rednaw।


आपके मामले में, आप क्या कर सकते हैं:

z = dict(x, **y)

यह वही होगा, जैसा कि आप चाहते हैं, अंतिम नियम को z , और कुंजी b के मान को दूसरे ( y ) dict के मान से ठीक से ओवरराइड किया जाए:

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

यदि आप पायथन 3 का उपयोग करते हैं, तो यह केवल थोड़ा और जटिल है। z बनाने के लिए:

z1 = dict(x.items() + y.items())
z2 = dict(x, **y)

एक और, संक्षिप्त, विकल्प:

% 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

नोट : यह एक लोकप्रिय उत्तर बन गया है, लेकिन यह इंगित करना महत्वपूर्ण है कि यदि y में कोई गैर-स्ट्रिंग कुंजी है, तो यह तथ्य कि यह बिल्कुल काम करता है वह एक सीपीथन कार्यान्वयन विवरण का दुरुपयोग है, और यह पायथन 3 में काम नहीं करता है , या पीपीपी, आयरनपीथन, या ज्योथन में। इसके अलावा, Guido एक प्रशंसक नहीं है । इसलिए मैं इस तकनीक को आगे-संगत या क्रॉस-कार्यान्वयन पोर्टेबल कोड के लिए अनुशंसा नहीं कर सकता, जिसका वास्तव में मतलब है कि इसे पूरी तरह से टालना चाहिए।


कॉपी का उपयोग न करने के दौरान मुझे लगता है कि सबसे अच्छा संस्करण होगा:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z4 = {}
z4.update(x)
z4.update(y)

यह dict(x.items() + y.items()) से तेज़ है लेकिन जितना तेज़ नहीं है n = copy(a); n.update(b) n = copy(a); n.update(b) , कम से कम CPython पर। यह संस्करण पायथन 3 में भी काम करता है यदि आप iteritems() को items() बदलते हैं, जो स्वचालित रूप से 2to3 टूल द्वारा किया जाता है।

व्यक्तिगत रूप से मुझे यह संस्करण सबसे अच्छा लगता है क्योंकि यह एक ही कार्यात्मक वाक्यविन्यास में जो कुछ भी चाहता है वह काफी अच्छा वर्णन करता है। एकमात्र मामूली समस्या यह है कि यह पूरी तरह से स्पष्ट नहीं करता है कि y से मानों को x से मानों पर प्राथमिकता मिलती है, लेकिन मुझे विश्वास नहीं है कि इसे समझना मुश्किल है।


पाइथोनिक बनें। comprehension प्रयोग करें:

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

पायथन 3 में, आप collections.ChainMap उपयोग कर सकते हैं .ChainMap जो एकल, अद्यतन करने योग्य दृश्य बनाने के लिए एक साथ कई डिक्ट्स या अन्य मैपिंग समूहबद्ध करता है:

from itertools import chain
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
dict(chain(x.iteritems(), y.iteritems()))

पायथन 3.5 (पीईपी 448) एक अच्छा सिंटैक्स विकल्प की अनुमति देता है:

def dict_merge(a, b):
  c = a.copy()
  c.update(b)
  return c

new = dict_merge(old, extras)

या और भी

print dict_merge(
      {'color':'red', 'model':'Mini'},
      {'model':'Ferrari', 'owner':'Carl'})

मैं कुछ समान चाहता था, लेकिन यह निर्दिष्ट करने की क्षमता के साथ कि डुप्लिकेट कुंजियों पर मूल्य कैसे विलय किए गए थे, इसलिए मैंने इसे हैक किया (लेकिन इसका परीक्षण नहीं किया)। जाहिर है यह एक अभिव्यक्ति नहीं है, लेकिन यह एक एकल समारोह कॉल है।

{
    'name': 'Pluutoo',
    'details': {
        'color': 'blue',
        'tail': True
    }
}

यदि आपको लगता है कि भेड़ के बच्चे बुरा हैं तो आगे नहीं पढ़ते हैं। अनुरोध के रूप में, आप एक अभिव्यक्ति के साथ तेज़ और स्मृति-कुशल समाधान लिख सकते हैं:

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

जैसा ऊपर बताया गया है, दो लाइनों का उपयोग करके या फ़ंक्शन लिखना संभवतः जाने का एक बेहतर तरीका है।


हालांकि सवाल का जवाब कई बार दिया जा चुका है, समस्या का यह सरल समाधान अभी तक सूचीबद्ध नहीं किया गया है।

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}

यह z0 और उपरोक्त वर्णित बुराई z2 जितना तेज़ है, लेकिन समझने और बदलने में आसान है।


(केवल Python2.7 * के लिए; Python3 * के लिए सरल समाधान हैं।)

यदि आप मानक लाइब्रेरी मॉड्यूल आयात करने के विपरीत नहीं हैं, तो आप कर सकते हैं

 from functools import reduce def merge_dicts(*dicts): return reduce(lambda a, d: a.update(d) or a, dicts, {}) 

(इसमें or aथोड़ा सा lambdaजरूरी है क्योंकि dict.updateहमेशा Noneसफलता पर लौटता है।)


आज तक सूचीबद्ध समाधानों के साथ मेरी समस्या यह है कि, मर्ज किए गए शब्दकोश में, कुंजी "बी" के लिए मान 10 है, लेकिन, मेरे सोचने के तरीके के लिए, यह 12 होना चाहिए। उस प्रकाश में, मैं निम्नलिखित प्रस्तुत करता हूं:

from functools import reduce

def merge_dicts(*dicts):
    return reduce(lambda a, d: a.update(d) or a, dicts, {})

परिणाम:

dict1 = {'a':1}
dict2 = {'b':2}
new_dict = {**dict1, **dict2}
>>>new_dict
{'a':1, 'a':2}

पायथन 2 के लिए:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> x, z = dict(x), x.update(y) or x
>>> x
{'a': 1, 'b': 2}
>>> y
{'c': 11, 'b': 10}
>>> z
{'a': 1, 'c': 11, 'b': 10}

पायथन 3 के लिए:

import timeit

n=100000
su = """
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
"""

def timeMerge(f,su,niter):
    print "{:4f} sec for: {:30s}".format(timeit.Timer(f,setup=su).timeit(n),f)

timeMerge("dict(x, **y)",su,n)
timeMerge("x.update(y)",su,n)
timeMerge("dict(x.items() + y.items())",su,n)
timeMerge("for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k] ",su,n)

#confirm for loop adds b entries together
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]
print "confirm b elements are added:",x

यह आउटपुट देता है: {'a': 1, 'c': 11, 'b': 10}


मैथ्यू के जवाब के लिए एक अभिव्यक्ति समाधान के लिए अग्रणी दुर्व्यवहार:

def union2(dict1, dict2):
    return dict(list(dict1.items()) + list(dict2.items()))

आपने कहा था कि आप एक अभिव्यक्ति चाहते थे, इसलिए मैंने lambda नाम को बांधने के लिए दुर्व्यवहार किया, और लैम्ब्डा की एक अभिव्यक्ति सीमा को ओवरराइड करने के लिए टुपल्स का उपयोग किया। क्रिंग करने के लिए स्वतंत्र महसूस करें।

यदि आप इसे कॉपी करने की परवाह नहीं करते हैं तो आप यह भी कर सकते हैं:

def union(*dicts):
    return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))

यह एक ही धक्का समझ के साथ किया जा सकता है:

 >>> x = {'a':1, 'b': 2} >>> y = {'b':10, 'c': 11} >>> { key: y[key] if key in y else x[key] for key in set(x) + set(y) } 

मेरे विचार में 'एकल अभिव्यक्ति' भाग के लिए सबसे अच्छा जवाब है क्योंकि कोई अतिरिक्त कार्य आवश्यक नहीं है, और यह छोटा है।


पायथन 3.5 में आप **नया शब्दकोश बनाने के लिए अनपैक का उपयोग कर सकते हैं । इस विधि को पिछले उत्तरों में नहीं दिखाया गया है। इसके अलावा, इसके {}बजाय उपयोग करना बेहतर है dict()। क्योंकि {}एक अजगर शाब्दिक है और dict()इसमें एक फंक्शन कॉल शामिल है।

 dict1 = {'a':1} dict2 = {'b':2} new_dict = {**dict1, **dict2} >>>new_dict {'a':1, 'a':2} 

भले ही उत्तर इस उथले शब्दकोश के लिए अच्छे थे , यहां परिभाषित तरीकों में से कोई भी वास्तव में एक गहरी शब्दकोश विलय नहीं करता है।

उदाहरणों का पालन करें:

{'two': True, 'one': {'extra': False}}

कोई इस तरह के कुछ के परिणाम की उम्मीद करेगा:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()+y.items())
print(z)

इसके बजाए, हमें यह मिलता है:

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items()|y.items())
print(z)

'एक' प्रविष्टि में 'गहराई' और 'अतिरिक्त' होना चाहिए, जो इसके शब्दकोश के अंदर आइटम के रूप में होना चाहिए यदि यह वास्तव में एक विलय था।

चेन का उपयोग करना भी काम नहीं करता है:

def merge(*dicts, **kv): 
      return { k:v for d in list(dicts) + [kv] for k,v in d.items() }

का परिणाम:

assert (merge({1:11,'a':'aaa'},{1:99, 'b':'bbb'},foo='bar')==\
    {1: 99, 'foo': 'bar', 'b': 'bbb', 'a': 'aaa'})

assert (merge(foo='bar')=={'foo': 'bar'})

assert (merge({1:11},{1:99},foo='bar',baz='quux')==\
    {1: 99, 'foo': 'bar', 'baz':'quux'})

assert (merge({1:11},{1:99})=={1: 99})

आरसीवीसिक द्वारा दी गई गहरी विलय ने भी वही परिणाम दिया है।

हां, यह नमूना शब्दकोशों को मर्ज करने के लिए काम करेगा, लेकिन उनमें से कोई भी विलय करने के लिए एक सामान्य तंत्र नहीं है। एक बार जब मैं एक विधि लिखता हूं जो एक सच्चा विलय करता है तो मैं इसे बाद में अपडेट करूंगा।


from collections import Counter
dict1 = {'a':1, 'b': 2}
dict2 = {'b':10, 'c': 11}
result = dict(Counter(dict1) + Counter(dict2))

z={i:d[i] for d in [x,y] for i in d}

>>> print z
{'a': 1, 'c': 11, 'b': 10}

इस तरह के छायादार और संदिग्ध उत्तरों में, यह चमकदार उदाहरण पाइथन में डिक्ट्स को मर्ज करने का एकमात्र अच्छा तरीका है, जो कि जीवन के लिए तानाशाह द्वारा समर्थित है Guido van Rossum ! किसी और ने इसका आधा सुझाव दिया, लेकिन इसे एक समारोह में नहीं रखा।

dict(x.items() | y.items())

देता है:

dict(x.viewitems() | y.viewitems())




merge