मेरे पास दो पायथन शब्दकोश हैं, और मैं एक अभिव्यक्ति लिखना चाहता हूं जो इन दो शब्दकोशों को लौटाता है, विलय (यानी संघ लेना)। 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() की अंतिम-एक-जीत संघर्ष-प्रबंधन वह है जिसे मैं भी ढूंढ रहा हूं।)

6067
Carl Meyer 2 सितंबर 2008, 11:44
यदि आप नेमस्पेस (डॉट नोटेशन डिक्ट्स) को मर्ज करना चाहते हैं तो इसे देखें:
 – 
Charlie Parker
29 सितंबर 2021, 22:06
मैंने इस प्रश्न को 5999 से 6000 तक बढ़ा दिया है! हुर्रे!
 – 
user17242583
15 नवम्बर 2021, 04:28

28 जवाब

एक विकल्प:

z = x.copy()
z.update(y)
697
Matthew Schinckel 2 सितंबर 2008, 17:00
91
यह स्पष्ट करने के लिए कि यह प्रश्न द्वारा प्रदान किए गए मानदंड को पूरा क्यों नहीं करता है: यह एक अभिव्यक्ति नहीं है और यह z वापस नहीं करता है।
 – 
Alexander Oh
21 मार्च 2013, 17:15
16
इसे इस तरह से रखें: यदि आपको अपना कोड उन लोगों को समझाते हुए टिप्पणियों की दो पंक्तियाँ डालने की आवश्यकता है जिन्हें आप अपना कोड सौंपते हैं ... क्या आपने वास्तव में इसे एक पंक्ति में किया है? :) मैं पूरी तरह से सहमत हूं कि पायथन इसके लिए अच्छा नहीं है: एक बहुत आसान तरीका होना चाहिए। हालांकि यह उत्तर अधिक पाइथोनिक है, क्या यह वास्तव में इतना स्पष्ट या स्पष्ट है? Update "मुख्य" कार्यों में से एक नहीं है जिसका लोग बहुत अधिक उपयोग करते हैं।
 – 
eric
19 अक्टूबर 2017, 16:07
6
ठीक है, अगर लोग इसे एक ऑनलाइनर बनाने पर जोर देते हैं, तो आप हमेशा (lambda z: z.update(y) or z)(x.copy()) :P . कर सकते हैं
 – 
towr
24 फरवरी 2020, 15:43
1
सिंगल-लाइन आवश्यकता को स्पष्टता का रास्ता देना चाहिए।
 – 
Thorbjørn Ravn Andersen
18 जून 2021, 18:36

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

z = dict(x, **y)

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

396
Carl Meyer 21 जिंदा 2016, 09:43
2
पायथन 3 और PyPy और PyPy 3 में ठीक काम करता है, बात नहीं कर सकता ज्योथन या आयरन। इस पैटर्न को देखते हुए स्पष्ट रूप से प्रलेखित है। (इस दस्तावेज़ में तीसरा कंस्ट्रक्टर फॉर्म देखें) मैं तर्क दूंगा कि यह "कार्यान्वयन विवरण" नहीं है, बल्कि जानबूझकर सुविधा का उपयोग है।
 – 
amcgregor
12 अप्रैल 2019, 16:10
11
आपने कुंजी वाक्यांश "यदि y में कोई गैर-स्ट्रिंग कुंजियाँ हैं" से चूक गए हैं। यही वह है जो Python3 में काम नहीं करता है; तथ्य यह है कि यह सीपीथन 2 में काम करता है एक कार्यान्वयन विवरण है जिस पर भरोसा नहीं किया जा सकता है। IFF आपकी सभी चाबियों के तार होने की गारंटी है, यह पूरी तरह से समर्थित विकल्प है।
 – 
Carl Meyer
10 मई 2019, 19:27

यह शायद एक लोकप्रिय उत्तर नहीं होगा, लेकिन आप लगभग निश्चित रूप से ऐसा नहीं करना चाहते हैं। अगर आप एक ऐसी कॉपी चाहते हैं जो मर्ज हो, तो कॉपी (या डीपकॉपी का इस्तेमाल करें, जो कि निर्भर करता है आप जो चाहते हैं उस पर) और फिर अपडेट करें। कोड की दो पंक्तियां .items() + .items() के साथ सिंगल लाइन निर्माण की तुलना में अधिक पठनीय - अधिक पाइथोनिक - हैं। स्पष्ट निहित से बेहतर है.

इसके अलावा, जब आप .items() (पायथन 3.0 से पहले) का उपयोग करते हैं, तो आप एक नई सूची बना रहे हैं जिसमें 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

IMO पहले दो के बीच की छोटी मंदी पठनीयता के लिए इसके लायक है। इसके अलावा, शब्दकोश निर्माण के लिए कीवर्ड तर्क केवल पायथन 2.3 में जोड़े गए थे, जबकि कॉपी () और अपडेट () पुराने संस्करणों में काम करेंगे।

247
twasbrillig 6 अगस्त 2014, 03:56

अनुवर्ती उत्तर में, आपने इन दो विकल्पों के सापेक्ष प्रदर्शन के बारे में पूछा:

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

मेरी मशीन पर, कम से कम (एक काफी सामान्य x86_64 पायथन 2.5.2 चल रहा है), वैकल्पिक z2 न केवल छोटा और सरल है, बल्कि काफी तेज भी है। आप पाइथन के साथ आने वाले timeit मॉड्यूल का उपयोग करके इसे अपने लिए सत्यापित कर सकते हैं।

उदाहरण 1 : समरूप शब्दकोष स्वयं में 20 क्रमागत पूर्णांकों का मानचित्रण करते हैं:

% 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 3.5 या उससे अधिक के कारक से जीतता है। अलग-अलग शब्दकोश काफी भिन्न परिणाम देते प्रतीत होते हैं, लेकिन z2 हमेशा आगे निकलते प्रतीत होते हैं। (यदि आपको समान परीक्षण के लिए असंगत परिणाम मिलते हैं, तो -r में डिफ़ॉल्ट 3 से बड़ी संख्या के साथ उत्तीर्ण होने का प्रयास करें।)

उदाहरण 2: गैर-अतिव्यापी शब्दकोश 252 लघु स्ट्रिंग्स को पूर्णांकों में मैप करते हैं और इसके विपरीत:

% 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 लगभग 10 के फ़ैक्टर से जीतता है। यह मेरी किताब में एक बहुत बड़ी जीत है!

उन दोनों की तुलना करने के बाद, मुझे आश्चर्य हुआ कि क्या z1 के खराब प्रदर्शन को दो आइटम सूचियों के निर्माण के लिए जिम्मेदार ठहराया जा सकता है, जिससे मुझे आश्चर्य हुआ कि क्या यह भिन्नता बेहतर काम कर सकती है:

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

कुछ त्वरित परीक्षण, उदा।

% 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

मुझे यह निष्कर्ष निकालने के लिए प्रेरित करता है कि z3, z1 से कुछ तेज है, लेकिन लगभग z2 जितना तेज नहीं है। निश्चित रूप से सभी अतिरिक्त टाइपिंग के लायक नहीं है।

इस चर्चा में अभी भी कुछ महत्वपूर्ण याद आ रही है, जो कि दो सूचियों को मर्ज करने के "स्पष्ट" तरीके से इन विकल्पों की प्रदर्शन तुलना है: update विधि का उपयोग करना। चीजों को भावों के साथ समान स्तर पर रखने की कोशिश करने के लिए, जिनमें से कोई भी x या y को संशोधित नहीं करता है, मैं इसे जगह में संशोधित करने के बजाय x की एक प्रति बनाने जा रहा हूं, जो निम्नानुसार है:

z0 = dict(x)
z0.update(y)

एक सामान्य परिणाम:

% 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

दूसरे शब्दों में, z0 और z2 का प्रदर्शन अनिवार्य रूप से एक जैसा लगता है। क्या आपको लगता है कि यह एक संयोग हो सकता है? मैं नही....

वास्तव में, मैं यह दावा करने के लिए इतना आगे जाऊंगा कि शुद्ध पायथन कोड के लिए इससे बेहतर कुछ करना असंभव है। और यदि आप सी एक्सटेंशन मॉड्यूल में काफी बेहतर कर सकते हैं, तो मुझे लगता है कि पाइथन लोगों को आपके कोड (या आपके दृष्टिकोण पर भिन्नता) को पायथन कोर में शामिल करने में रुचि हो सकती है। पायथन कई जगहों पर dict का उपयोग करता है; इसके संचालन को अनुकूलित करना एक बड़ी बात है।

आप इसे इस प्रकार भी लिख सकते हैं

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

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

180
the Tin Man 10 जिंदा 2015, 05:32
7
यह पायथन 3 में काम नहीं करता है; items() के योग्य नहीं है, और iteritems मौजूद नहीं है।
 – 
Antti Haapala
16 मार्च 2015, 08:50

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

>>> from collections import ChainMap
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(ChainMap({}, y, x))
>>> for k, v in z.items():
        print(k, '-->', v)
    
a --> 1
b --> 10
c --> 11

पायथन 3.5 और बाद के संस्करण के लिए अपडेट करें: आप PEP 448< का उपयोग कर सकते हैं / ए> विस्तारित शब्दकोश पैकिंग और अनपैकिंग। यह तेज़ और आसान है:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> {**x, **y}
{'a': 1, 'b': 10, 'c': 11}

पायथन 3.9 और बाद के संस्करण के लिए अपडेट: आप PEP 584 का उपयोग कर सकते हैं संघ संचालक:

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> x | y
{'a': 1, 'b': 10, 'c': 11}
170
Raymond Hettinger 11 पद 2020, 09:43
4
लेकिन चैनमैप का उपयोग करते समय सावधान रहना चाहिए कि यदि आपके पास डुप्लीकेट कुंजियाँ हैं तो पहले मैपिंग के मूल्यों का उपयोग किया जाता है और जब आप del को कॉल करते हैं तो चेनमैप सी उस कुंजी की पहली मैपिंग को हटा देगा।
 – 
Slayer
14 फरवरी 2017, 08:14
9
आप इससे और क्या करने की अपेक्षा करेंगे? यह सामान्य तरीका है जंजीर नामस्थान काम करते हैं। विचार करें कि $PATH बैश में कैसे काम करता है। पथ पर एक निष्पादन योग्य को हटाना एक और निष्पादन योग्य को उसी नाम के साथ आगे की ओर नहीं रोकता है।
 – 
Raymond Hettinger
15 फरवरी 2017, 10:24
3
हेटिंगर मैं सहमत हूं, बस एक सावधानी जोड़ी। इसके बारे में शायद ज्यादातर लोगों को पता न हो। :डी
 – 
Slayer
15 फरवरी 2017, 18:15
आप इससे बचने के लिए dict पर कास्ट कर सकते हैं, यानी: dict(ChainMap({}, y, x))
 – 
wjandrea
15 जुलाई 2019, 19:30
1
सुझाई गई संपादन कतार भरी हुई है, लेकिन किसी ने उत्तर में @wjandrea से संशोधन किया है, जो गलत है - यह अब a single, updateable view नहीं है। यह संपादन वापस किया जाना चाहिए।
 – 
Gloweye
19 जुलाई 2021, 15:08

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

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
145
Rainy 13 सितंबर 2014, 23:56
आसान समाधान जब छोटे और सरल समाधानों के डिफ़ॉल्ट व्यवहार (दूसरे शब्दकोश द्वारा सामान्य कुंजी के मूल्यों के प्रतिस्थापन) की कामना नहीं की जाती है। पायथन 3 के लिए, iteritems() अब डिक्ट्स में उपलब्ध नहीं है, और कोई इसके बजाय आइटम्स() का उपयोग कर सकता है।
 – 
Corentor
5 मार्च 2021, 17:22

पुनरावर्ती/गहरा अद्यतन एक तानाशाही

def deepupdate(original, update):
    """
    Recursively update a dict.
    Subdict's won't be overwritten but also updated.
    """
    for key, value in original.iteritems(): 
        if key not in update:
            update[key] = value
        elif isinstance(value, dict):
            deepupdate(value, update[key]) 
    return update

प्रदर्शन:

pluto_original = {
    'name': 'Pluto',
    'details': {
        'tail': True,
        'color': 'orange'
    }
}

pluto_update = {
    'name': 'Pluutoo',
    'details': {
        'color': 'blue'
    }
}

print deepupdate(pluto_original, pluto_update)

आउटपुट:

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

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

115
Dawid Gosławski 18 पद 2015, 14:19
2
यह प्रश्न का उत्तर नहीं देता है। प्रश्न स्पष्ट रूप से एक नया शब्दकोश, z, मूल शब्दकोशों से, x और y के लिए पूछता है, y के मानों के साथ x के स्थान पर - एक अद्यतन शब्दकोश नहीं। यह उत्तर x से मान जोड़कर y को इन-प्लेस संशोधित करता है। इससे भी बदतर, यह इन मूल्यों की नकल नहीं करता है, इसलिए कोई संशोधित शब्दकोश, y को और संशोधित कर सकता है, और संशोधनों को शब्दकोश x में प्रतिबिंबित किया जा सकता है। @ जेरोम मुझे आशा है कि यह कोड आपके आवेदन के लिए कोई बग नहीं पैदा कर रहा है - कम से कम मूल्यों की प्रतिलिपि बनाने के लिए डीपकॉपी का उपयोग करने पर विचार करें।
 – 
Aaron Hall
9 नवम्बर 2018, 05:14
2
सहमत हैं कि यह सवाल का जवाब नहीं देता है। लेकिन यह मेरी जरूरत का जवाब देता है। मैं उन सीमाओं को समझता हूं, लेकिन मेरे मामले में यह कोई मुद्दा नहीं है। इसके बारे में सोचकर, शायद नाम भ्रामक है, क्योंकि यह एक गहरी प्रति पैदा कर सकता है, जो यह प्रदान नहीं करता है। लेकिन यह गहरे घोंसले के शिकार को संबोधित करता है। मार्टेलिबोट से एक और कार्यान्वयन यहां दिया गया है: अलग-अलग गहराई का एक नेस्टेड शब्दकोश%233233356"> stackoverflow.com/questions/3232943/…।
 – 
Jérôme
9 नवम्बर 2018, 16:24

कॉपी का उपयोग न करते समय मैं जो सबसे अच्छा संस्करण सोच सकता था वह होगा:

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

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

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

89
driax 14 अक्टूबर 2010, 22:55

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

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}

पायथन 3.9 में आप | . का भी उपयोग करते हैं और |= पीईपी 584 से नीचे दिए गए उदाहरण के साथ

d = {'spam': 1, 'eggs': 2, 'cheese': 3}
e = {'cheese': 'cheddar', 'aardvark': 'Ethel'}
d | e
# {'spam': 1, 'eggs': 2, 'cheese': 'cheddar', 'aardvark': 'Ethel'}
92
Bilal Syed Hussain 4 मई 2020, 00:16
यह समाधान किस प्रकार dict(x, **y)-समाधान से बेहतर है? जैसा कि आपने (@CarlMeyer) ने अपने स्वयं के उत्तर के नोट में उल्लेख किया है (stackoverflow.com/a/39858/2798610) Guido उस समाधान को अवैध मानता है।
 – 
Blackeagle52
4 मार्च 2015, 14:09
16
गुइडो (बहुत अच्छे) कारण के लिए dict(x, **y) को नापसंद करता है क्योंकि यह y पर निर्भर करता है, जिसमें केवल कुंजियाँ होती हैं जो वैध कीवर्ड तर्क नाम होती हैं (जब तक कि आप CPython 2.7 का उपयोग नहीं कर रहे हैं, जहां तानाशाह निर्माता धोखा देता है)। यह आपत्ति/प्रतिबंध पीईपी 448 पर लागू नहीं होता है, जो कि ** अनपैकिंग सिंटैक्स को डिक्ट लिटरल्स के लिए सामान्यीकृत करता है। तो इस समाधान में बिना किसी नुकसान के dict(x, **y) के समान ही संक्षिप्तीकरण है।
 – 
Carl Meyer
5 मार्च 2015, 01:24
x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z = dict(x.items() + y.items())
print z

दोनों शब्दकोशों ('बी') में चाबियों वाले आइटम के लिए, आप यह नियंत्रित कर सकते हैं कि कौन सा अंतिम आउटपुट में समाप्त होता है।

84
Greg Hewgill 2 सितंबर 2008, 11:49
7
पायथन 3 में आपको TypeError: असमर्थित ऑपरेंड प्रकार +: 'dict_items' और 'dict_items' के लिए मिलेगा ... आपको सूची के साथ प्रत्येक dict को समाहित करना चाहिए() जैसे: dict (सूची (x.items ()) + सूची (वाई.आइटम ()))
 – 
justSaid
26 अप्रैल 2019, 11:45

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

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

यह ऊपर बताए गए z0 और दुष्ट z2 जितना तेज़ है, लेकिन समझने और बदलने में आसान है।

64
phobie 14 अक्टूबर 2011, 20:12
3
लेकिन यह एक अभिव्यक्ति के बजाय तीन कथन हैं
 – 
fortran
18 अक्टूबर 2011, 19:44
16
हां! उल्लिखित एक-अभिव्यक्ति-समाधान या तो धीमे हैं या बुरे हैं। अच्छा कोड पठनीय और रखरखाव योग्य है। तो समस्या सवाल है जवाब नहीं। हमें किसी समस्या का सबसे अच्छा समाधान पूछना चाहिए, न कि एक-पंक्ति-समाधान के लिए।
 – 
phobie
28 अक्टूबर 2011, 07:36
10
z4 = {} को खो दें और अगली पंक्ति को z4 = x.copy() में बदल दें - केवल अच्छे कोड से बेहतर अनावश्यक चीजें नहीं करता है (जो इसे और भी अधिक पठनीय और रखरखाव योग्य बनाता है)।
 – 
martineau
8 मार्च 2013, 19:10
3
आपका सुझाव इसे मैथ्यूज के उत्तर में बदल देगा। जबकि उनका उत्तर ठीक है, मुझे लगता है कि मेरा अधिक पठनीय और बेहतर रखरखाव योग्य है। अतिरिक्त लाइन केवल खराब होगी यदि इसे निष्पादन समय खर्च करना होगा।
 – 
phobie
6 मई 2013, 15:50
मेरा सुझाव है कि आप इसे एक समारोह में डाल दें
 – 
Corman
15 जून 2020, 02:16
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'})

देता है:

{'color': 'red', 'owner': 'Carl', 'model': 'Ferrari'}
60
Sam Watkins 6 अगस्त 2012, 13:30

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

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}

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

53
EMS 23 नवम्बर 2011, 22:20

पाइथोनिक हो। एक समझ का उपयोग करें:

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

>>> print z
{'a': 1, 'c': 11, 'b': 10}
46
Robino 29 सितंबर 2016, 13:45
1
एक समारोह के रूप में: def dictmerge(*args): return {i:d[i] for d in args for i in d}
 – 
jessexknight
6 जून 2018, 21:27
3
कुंजी/मान युग्मों को सीधे पुनरावृत्त करके लुकअप सहेजें: z={k: v for d in (x, y) for k, v in d.items()}
 – 
ShadowRanger
5 मार्च 2019, 22:33

Python3 में, items विधि अब कोई सूची नहीं देता, बल्कि एक दृश्य देता है, जो एक सेट की तरह कार्य करता है। इस मामले में आपको सेट यूनियन लेने की आवश्यकता होगी क्योंकि + के साथ काम करने से काम नहीं चलेगा:

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

संस्करण 2.7 में python3 जैसे व्यवहार के लिए, viewitems विधि को items के स्थान पर काम करना चाहिए:

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

मैं वैसे भी इस संकेतन को पसंद करता हूं क्योंकि इसे संयोजन के बजाय एक सेट यूनियन ऑपरेशन के रूप में सोचना अधिक स्वाभाविक लगता है (जैसा कि शीर्षक से पता चलता है)।

संपादित करें:

अजगर 3 के लिए कुछ और अंक। सबसे पहले, ध्यान दें कि dict(x, **y) चाल अजगर 3 में तब तक काम नहीं करेगी जब तक कि y में कुंजियाँ तार न हों।

साथ ही, रेमंड हेटिंगर का चैनमैप answer बहुत सुंदर है, क्योंकि यह तर्कों के रूप में मनमाने ढंग से संख्याओं को ले सकता है, लेकिन दस्तावेज़ों से ऐसा लगता है कि यह क्रमिक रूप से प्रत्येक लुकअप के लिए सभी dicts की सूची को देखता है:

लुकअप अंतर्निहित मैपिंग को क्रमिक रूप से तब तक खोजता है जब तक कि कोई कुंजी न मिल जाए।

यदि आपके आवेदन में बहुत सारे लुकअप हैं तो यह आपको धीमा कर सकता है:

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

तो लुकअप के लिए परिमाण धीमी गति के क्रम के बारे में। मैं चैनमैप का प्रशंसक हूं, लेकिन जहां कई लुकअप हो सकते हैं, वहां कम व्यावहारिक लगता है।

41
Community 23 मई 2017, 15:34

दुरुपयोग के कारण मैथ्यू का उत्तर के लिए एक-अभिव्यक्ति समाधान:

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

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

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

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = (x.update(y), x)[1]
>>> z
{'a': 1, 'b': 10, 'c': 11}
29
Community 23 मई 2017, 15:34

दो शब्दकोश

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

n शब्दकोश

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

sum का प्रदर्शन खराब है। देखें https://mathieularose.com/how -नॉट-टू-फ्लैटन-ए-लिस्ट-ऑफ-लिस्ट्स-इन-पायथन/

32
Mathieu Larose 2 अक्टूबर 2016, 21:16

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

उदाहरण अनुसरण करते हैं:

a = { 'one': { 'depth_2': True }, 'two': True }
b = { 'one': { 'extra': False } }
print dict(a.items() + b.items())

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

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

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

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

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

श्रृंखला का उपयोग करना भी काम नहीं करता है:

from itertools import chain
print dict(chain(a.iteritems(), b.iteritems()))

का परिणाम:

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

Rcwesick ने जो गहरा मर्ज दिया है, वह भी वही परिणाम देता है।

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

24
Thanh Lim 4 अगस्त 2012, 03:36

यहाँ और अन्य जगहों पर विचारों को आकर्षित करते हुए मैंने एक फ़ंक्शन को समझा है:

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

उपयोग (पायथन 3 में परीक्षण):

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

आप इसके बजाय लैम्ब्डा का उपयोग कर सकते हैं।

16
Bijou Trouvaille 19 जुलाई 2013, 09:49

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

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

परिणाम:

0.049465 sec for: dict(x, **y)
0.033729 sec for: x.update(y)                   
0.150380 sec for: dict(x.items() + y.items())   
0.083120 sec for: for k in y.keys(): x[k] = k in x and x[k]+y[k] or y[k]

confirm b elements are added: {'a': 1, 'c': 11, 'b': 12}
16
upandacross 3 पद 2013, 22:11
1
आपकी रुचि cytoolz.merge_with (toolz.readthedocs में हो सकती है .io/en/latest/…)
 – 
bli
16 फरवरी 2017, 16:44
from collections import Counter
dict1 = {'a':1, 'b': 2}
dict2 = {'b':10, 'c': 11}
result = dict(Counter(dict1) + Counter(dict2))

इससे आपकी समस्या का समाधान हो जाना चाहिए।

15
reetesh11 30 नवम्बर 2015, 16:04
मैं + के बजाय काउंटर के .update() का उपयोग करने की अनुशंसा करूंगा। ऐसा इसलिए है, क्योंकि यदि योग किसी भी कुंजी के लिए 0 के मान का परिणाम देता है, तो काउंटर उसे हटा देगा।
 – 
Eyong Kevin Enowanyo
7 अगस्त 2021, 21:23

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

यदि आप एक मानक पुस्तकालय मॉड्यूल आयात करने के खिलाफ नहीं हैं, तो आप कर सकते हैं

from functools import reduce

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

(lambda में or a बिट आवश्यक है क्योंकि dict.update हमेशा सफलता पर None लौटाता है।)

17
kjo 28 मार्च 2016, 16:13
>>> 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}
8
John La Rooy 13 नवम्बर 2013, 14:01
यह विधि अपनी प्रति के साथ x को अधिलेखित कर देती है। अगर x एक फ़ंक्शन तर्क है तो यह काम नहीं करेगा (देखें उदाहरण)
 – 
bartolo-otrit
22 फरवरी 2019, 12:27

यह इतना मूर्खतापूर्ण है कि .update कुछ भी नहीं लौटाता।
मैं समस्या को हल करने के लिए बस एक साधारण सहायक फ़ंक्शन का उपयोग करता हूं:

def merge(dict1,*dicts):
    for dict2 in dicts:
        dict1.update(dict2)
    return dict1

उदाहरण:

merge(dict1,dict2)
merge(dict1,dict2,dict3)
merge(dict1,dict2,dict3,dict4)
merge({},dict1,dict2)  # this one returns a new copy
17
GetFree 2 मार्च 2014, 05:44

अगर आपको x को बदलने में कोई आपत्ति नहीं है,

x.update(y) or x

सरल, पठनीय, प्रदर्शनकारी। आप जानते हैं update() हमेशा None लौटाते हैं, जो एक गलत मान है। अतः उपरोक्त व्यंजक हमेशा अद्यतन करने के बाद x का मूल्यांकन करेगा।

मानक पुस्तकालय में अधिकांश परिवर्तनशील विधियाँ (जैसे .update()) सम्मेलन द्वारा None लौटाती हैं, इसलिए इस प्रकार का पैटर्न उन पर भी काम करेगा। हालाँकि, यदि आप एक तानाशाही उपवर्ग या किसी अन्य विधि का उपयोग कर रहे हैं जो इस सम्मेलन का पालन नहीं करता है, तो or अपना बायाँ संकार्य वापस कर सकता है, जो वह नहीं हो सकता जो आप चाहते हैं। इसके बजाय, आप एक टपल डिस्प्ले और इंडेक्स का उपयोग कर सकते हैं, जो इस बात की परवाह किए बिना काम करता है कि पहला तत्व क्या मूल्यांकन करता है (हालाँकि यह उतना सुंदर नहीं है):

(x.update(y), x)[-1]

यदि आपके पास अभी तक एक वेरिएबल में x नहीं है, तो आप असाइनमेंट स्टेटमेंट का उपयोग किए बिना स्थानीय बनाने के लिए lambda का उपयोग कर सकते हैं। यह lambda को लेट एक्सप्रेशन के रूप में उपयोग करने के बराबर है, जो कार्यात्मक भाषाओं में एक सामान्य तकनीक है, लेकिन शायद अनपायथनिक है।

(lambda x: x.update(y) or x)({'a': 1, 'b': 2})

हालांकि यह नए वालरस ऑपरेटर (केवल पायथन 3.8+) के निम्नलिखित उपयोग से अलग नहीं है,

(x := {'a': 1, 'b': 2}).update(y) or x

खासकर यदि आप एक डिफ़ॉल्ट तर्क का उपयोग करते हैं:

(lambda x={'a': 1, 'b': 2}: x.update(y) or x)()

अगर आप एक कॉपी चाहते हैं, तो PEP 584 स्टाइल x | y 3.9+ पर सबसे पाइथोनिक है। अगर आपको पुराने संस्करणों का समर्थन करना चाहिए, PEP 448 शैली {**x, **y} 3.5+ के लिए सबसे आसान है। लेकिन अगर यह आपके (और भी पुराने) पायथन संस्करण में उपलब्ध नहीं है, तो लेट एक्सप्रेशन पैटर्न यहां भी काम करता है।

(lambda z=x.copy(): z.update(y) or z)()

(यह निश्चित रूप से, लगभग (z := x.copy()).update(y) or z के बराबर है, लेकिन यदि आपका पायथन संस्करण उसके लिए काफी नया है, तो पीईपी 448 शैली उपलब्ध होगी।)

22
gilch 29 मई 2021, 09:33

एक तानाशाही समझ का उपयोग करते हुए, आप कर सकते हैं

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}

dc = {xi:(x[xi] if xi not in list(y.keys()) 
           else y[xi]) for xi in list(x.keys())+(list(y.keys()))}

देता है

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

समझ में if else के सिंटैक्स पर ध्यान दें

{ (some_key if condition else default_key):(something_if_true if condition 
          else something_if_false) for key, value in dict_.items() }
5
kiriloff 27 मई 2013, 13:04
8
मुझे एक तानाशाही समझ का उपयोग करने का विचार पसंद है, लेकिन आपका कार्यान्वयन कमजोर है। केवल ... in y के बजाय ... in list(y.keys()) का उपयोग करना पागलपन है।
 – 
wim
19 फरवरी 2014, 00:18

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

उपयोग के मामले के आधार पर दिए गए इनपुट शब्दकोशों का "वास्तविक" मर्ज किया गया शब्दकोश बनाना आवश्यक नहीं हो सकता है। एक दृश्य जो ऐसा करता है कई मामलों में पर्याप्त हो सकता है, i. इ। एक ऑब्जेक्ट जो मर्ज किए गए शब्दकोश की तरह पसंद काम करता है, उसकी पूरी तरह से गणना किए बिना होगा। मर्ज किए गए शब्दकोश का एक आलसी संस्करण, इसलिए बोलने के लिए।

पायथन में, यह अपेक्षाकृत सरल है और मेरी पोस्ट के अंत में दिखाए गए कोड के साथ किया जा सकता है। यह दिया गया है, मूल प्रश्न का उत्तर होगा:

z = MergeDict(x, y)

इस नई वस्तु का उपयोग करते समय, यह एक मर्ज किए गए शब्दकोश की तरह व्यवहार करेगा, लेकिन मूल शब्दकोशों को अछूता छोड़ते हुए इसमें निरंतर निर्माण समय और निरंतर स्मृति पदचिह्न होगा। प्रस्तावित अन्य समाधानों की तुलना में इसे बनाना सस्ता है।

बेशक, यदि आप परिणाम का बहुत अधिक उपयोग करते हैं, तो आप किसी बिंदु पर उस सीमा तक पहुंच जाएंगे जहां वास्तविक मर्ज किए गए शब्दकोश को बनाना सबसे तेज़ समाधान होता। जैसा कि मैंने कहा, यह आपके उपयोग के मामले पर निर्भर करता है।

यदि आपने कभी महसूस किया है कि आप एक वास्तविक मर्ज किए गए dict को पसंद करेंगे, तो dict(z) पर कॉल करने से यह उत्पादन होगा (लेकिन निश्चित रूप से अन्य समाधानों की तुलना में अधिक महंगा है, इसलिए यह केवल ध्यान देने योग्य है)।

आप इस वर्ग का उपयोग एक प्रकार की कॉपी-ऑन-राइट डिक्शनरी बनाने के लिए भी कर सकते हैं:

a = { 'x': 3, 'y': 4 }
b = MergeDict(a)  # we merge just one dict
b['x'] = 5
print b  # will print {'x': 5, 'y': 4}
print a  # will print {'y': 4, 'x': 3}

यहाँ MergeDict का सीधा-सीधा कोड है:

class MergeDict(object):
  def __init__(self, *originals):
    self.originals = ({},) + originals[::-1]  # reversed

  def __getitem__(self, key):
    for original in self.originals:
      try:
        return original[key]
      except KeyError:
        pass
    raise KeyError(key)

  def __setitem__(self, key, value):
    self.originals[0][key] = value

  def __iter__(self):
    return iter(self.keys())

  def __repr__(self):
    return '%s(%s)' % (
      self.__class__.__name__,
      ', '.join(repr(original)
          for original in reversed(self.originals)))

  def __str__(self):
    return '{%s}' % ', '.join(
        '%r: %r' % i for i in self.iteritems())

  def iteritems(self):
    found = set()
    for original in self.originals:
      for k, v in original.iteritems():
        if k not in found:
          yield k, v
          found.add(k)

  def items(self):
    return list(self.iteritems())

  def keys(self):
    return list(k for k, _ in self.iteritems())

  def values(self):
    return list(v for _, v in self.iteritems())
6
Alfe 18 मई 2016, 18:57
2
मैंने अब तक देखा है कि कुछ उत्तर ChainMap नामक एक वर्ग को संदर्भित करते हैं जो केवल पायथन 3 में उपलब्ध है और जो कमोबेश वही करता है जो मेरा कोड करता है। सब कुछ ध्यान से नहीं पढ़ने के लिए मुझ पर शर्म आती है। लेकिन यह देखते हुए कि यह केवल पायथन 3 के लिए मौजूद है, कृपया मेरे उत्तर को पायथन 2 उपयोगकर्ताओं के लिए योगदान के रूप में लें ;-)
 – 
Alfe
18 मई 2016, 19:10
5
ChainMap को पहले के Pythons के लिए बैकपोर्ट किया गया था: pypi.python.org/pypi/chainmap
 – 
clacke
28 जुलाई 2016, 14:19

पायथन 3.9 में नया: का प्रयोग करें यूनियन ऑपरेटर (|) dict को sets के समान मर्ज करने के लिए:

>>> d = {'a': 1, 'b': 2}
>>> e = {'a': 9, 'c': 3}
>>> d | e
{'a': 9, 'b': 2, 'c': 3}

मेल खाने वाली कुंजियों के लिए, दाएं dict को प्राथमिकता दी जाती है

यह |= के लिए एक dict को इन-प्लेस संशोधित करने के लिए भी काम करता है:

>>> e |= d    # e = e | d
>>> e
{'a': 1, 'c': 3, 'b': 2}
18
xjcl 30 नवम्बर 2020, 00:49