दिलचस्प पोस्ट
बाश में वाइल्ड कमांड और इसका सामान्य उपयोग विम के लिए \ ra न्यूलाइन क्यों है? पृष्ठभूमि रंग चर पर आधारित सशर्त सीएसएस पायथन में बड़ी फ़ाइल से एक पंक्ति को हटाने का सबसे तेज़ तरीका व्यावहारिक गैर-छवि आधारित कैप्चा दृष्टिकोण क्या है? मैं अपने क्रोम एक्सटेंशन में स्थानीय रूप से जानकारी कैसे बचा सकता हूं? आप जावा में एक सरणी में सभी नंबरों का योग कैसे पाते हैं? क्यों नहीं ProjectName- Prefix.pch Xcode 6 में स्वचालित रूप से बनाया है? Es6 कक्षाओं का उपयोग करते समय प्रतिक्रिया में "सुपर ()" और "सुपर (प्रोपी)" के बीच अंतर क्या है? आत्मा क्यूई के एकल-सदस्यीय संरचना के साथ विशेषता प्रसार का मुद्दा ASP.NET MVC रेजर पास मॉडल लेआउट के लिए कैसे एक सरल एंड्रॉइड पॉपअप विंडो बनाने के लिए? त्रुटि संदेश है (# 12) बायो फ़ील्ड v2.8 और उच्चतर संस्करणों के लिए पदावनत है Google Drive API उपयोग की सीमा क्या है? विंडोज में गिट सिमलिंक

शब्दकोश मर्ज के शब्दकोश

मुझे कई शब्दकोशों को मर्ज करने की आवश्यकता है, उदाहरण के लिए मेरे पास क्या है:

dict1 = {1:{"a":{A}},2:{"b":{B}}} dict2 = {2:{"c":{C}}, 3:{"d":{D}} 

A B C और D C पेड़ की पत्तियां, जैसे {"info1":"value", "info2":"value2"}

शब्दकोशों का एक अज्ञात स्तर (गहराई) है, यह {2:{"c":{"z":{"y":{C}}}}}

मेरे मामले में यह नोड्स के साथ एक निर्देशिका / फाइल संरचना का प्रतिनिधित्व करता है और दस्तावेज़ होने वाली पत्तियों को छोड़ देता है

मैं dict3={1:{"a":{A}},2:{"b":{B},"c":{C}},3:{"d":{D}}} प्राप्त करने के लिए मर्ज करना चाहता हूं dict3={1:{"a":{A}},2:{"b":{B},"c":{C}},3:{"d":{D}}}

मुझे यकीन नहीं है कि मैं आसानी से पायथन के साथ कैसे कर सकता हूं

Solutions Collecting From Web of "शब्दकोश मर्ज के शब्दकोश"

यह वास्तव में बहुत मुश्किल है – खासकर जब आप एक उपयोगी त्रुटि संदेश चाहते हैं, जब चीजें असंगत हों, जबकि सही ढंग से डुप्लिकेट लेकिन सुसंगत प्रविष्टियां (कुछ अन्य कोई जवाब नहीं है) स्वीकार कर रहा है।

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

 def merge(a, b, path=None): "merges b into a" if path is None: path = [] for key in b: if key in a: if isinstance(a[key], dict) and isinstance(b[key], dict): merge(a[key], b[key], path + [str(key)]) elif a[key] == b[key]: pass # same leaf value else: raise Exception('Conflict at %s' % '.'.join(path + [str(key)])) else: a[key] = b[key] return a # works print(merge({1:{"a":"A"},2:{"b":"B"}}, {2:{"c":"C"},3:{"d":"D"}})) # has conflict merge({1:{"a":"A"},2:{"b":"B"}}, {1:{"a":"A"},2:{"b":"C"}}) 

ध्यान दें कि यह a बदलता ab की सामग्री को a जोड़ दिया जाता a (जो भी वापस आ गया है) अगर आप इसे रखना चाहते हैं तो आप उसे merge(dict(a), b) जैसे कॉल कर सकते हैं।

एजीएफ ने बताया (नीचे) कि आपके पास दो से अधिक डिकट हो सकते हैं, जिस स्थिति में आप उपयोग कर सकते हैं:

 reduce(merge, [dict1, dict2, dict3...]) 

जहां सब कुछ dict1 में जोड़ा जाएगा

[नोट – मैंने पहला तर्क बदलने के लिए मेरा प्रारंभिक जवाब संपादित किया; जो "कम" को समझाने में आसान बनाता है]

अजगर 3 में ps, आपको from functools import reduce आवश्यकता होगी

जनरेटर का उपयोग करने के लिए यहां एक आसान तरीका है:

 def mergedicts(dict1, dict2): for k in set(dict1.keys()).union(dict2.keys()): if k in dict1 and k in dict2: if isinstance(dict1[k], dict) and isinstance(dict2[k], dict): yield (k, dict(mergedicts(dict1[k], dict2[k]))) else: # If one of the values is not a dict, you can't continue merging it. # Value from second dict overrides one in first and we move on. yield (k, dict2[k]) # Alternatively, replace this with exception raiser to alert you of value conflicts elif k in dict1: yield (k, dict1[k]) else: yield (k, dict2[k]) dict1 = {1:{"a":"A"},2:{"b":"B"}} dict2 = {2:{"c":"C"},3:{"d":"D"}} print dict(mergedicts(dict1,dict2)) 

यह प्रिंट करता है:

 {1: {'a': 'A'}, 2: {'c': 'C', 'b': 'B'}, 3: {'d': 'D'}} 

इस प्रश्न के साथ एक मुद्दा यह है कि डिक् के मूल्य आंकड़ों के आकस्मिक जटिल टुकड़े हो सकते हैं। इन और अन्य उत्तरों के आधार पर मैं इस कोड के साथ आया था:

 class YamlReaderError(Exception): pass def data_merge(a, b): """merges b into a and return merged result NOTE: tuples and arbitrary objects are not handled as it is totally ambiguous what should happen""" key = None # ## debug output # sys.stderr.write("DEBUG: %s to %s\n" %(b,a)) try: if a is None or isinstance(a, str) or isinstance(a, unicode) or isinstance(a, int) or isinstance(a, long) or isinstance(a, float): # border case for first run or if a is a primitive a = b elif isinstance(a, list): # lists can be only appended if isinstance(b, list): # merge lists a.extend(b) else: # append to list a.append(b) elif isinstance(a, dict): # dicts must be merged if isinstance(b, dict): for key in b: if key in a: a[key] = data_merge(a[key], b[key]) else: a[key] = b[key] else: raise YamlReaderError('Cannot merge non-dict "%s" into dict "%s"' % (b, a)) else: raise YamlReaderError('NOT IMPLEMENTED "%s" into "%s"' % (b, a)) except TypeError, e: raise YamlReaderError('TypeError "%s" in key "%s" when merging "%s" into "%s"' % (e, key, b, a)) return a 

मेरा उपयोग केस YAML फ़ाइलों को मर्ज कर रहा है, जहां मुझे केवल संभव डेटा प्रकारों के सबसेट के साथ काम करना है इसलिए मैं ट्यूपल्स और अन्य ऑब्जेक्ट्स को अनदेखा कर सकता हूं। मेरे लिए एक समझदार मर्ज लॉजिक का मतलब है

  • स्केलेर की जगह
  • सूची जोड़ें
  • लापता कुंजियों को जोड़कर और मौजूदा कुंजियों को अपडेट करके मर्ज करें

बाकी सब कुछ और अप्रत्याशित रूप से एक त्रुटि में परिणाम

यदि आपके पास शब्दकोशों का अज्ञात स्तर है, तो मैं पुनरावर्ती फ़ंक्शन का सुझाव दूंगा:

 def combineDicts(dictionary1, dictionary2): output = {} for item, value in dictionary1.iteritems(): if dictionary2.has_key(item): if isinstance(dictionary2[item], dict): output[item] = combineDicts(value, dictionary2.pop(item)) else: output[item] = value for item, value in dictionary2.iteritems(): output[item] = value return output 

@ इंड्रू कुकी के आधार पर यह संस्करण लेखों की नेस्टेड सूची को संभालता है और विकल्प को अपडेट करने की अनुमति देता है

 डेफ मर्ज (ए, बी, पथ = कोई नहीं, अपडेट = ट्रू):
     "Http://stackoverflow.com/questions/7204805/python-dictionaries-of-dictionaries-merge"
     "बी में विलीन हो जाता है"
     यदि पथ कोई नहीं है: पथ = []
     बी में कुंजी के लिए:
         यदि एक में कुंजी:
             यदि इस्टेंस (एक [कुंजी], डिक्टिक) और इस्टेंस (बी [कुंजी], डिक्ट):
                 मर्ज (एक [कुंजी], बी [कुंजी], पथ + [स्ट्र (कुंजी))
             एलीफ एक [कुंजी] == बी [कुंजी]:
                 पास # समान पत्ती मूल्य
             एलिफ इस्टेंस (एक [कुंजी], लिस्ट) और इस्टेंस (बी [कुंजी], सूची):
                 आईडीएक्स के लिए, मान की गणना करें (बी [कुंजी]):
                     एक [कुंजी] [idx] = मर्ज (एक [कुंजी] [idx], बी [कुंजी] [idx], पथ + [str (कुंजी), str (idx)], अद्यतन = अद्यतन)
             elif अद्यतन:
                 एक [कुंजी] = बी [कुंजी]
             अन्य:
                 अपवाद उठाना ('% s'% पर संघर्ष ''। शामिल होना (पथ + [स्ट्र (कुंजी)])
         अन्य:
             एक [कुंजी] = बी [कुंजी]
     वापस आओ

शब्दकोश मर्ज के शब्दकोश

जैसा कि ये विहित प्रश्न है (कुछ गैर-सामान्यताओं के बावजूद) मैं इस मुद्दे को सुलझाने के लिए कैननिक पायथन संबंधी दृष्टिकोण प्रदान कर रहा हूं।

सरल मामला: "पत्तियां नेस्टेड डिक्ट्स हैं जो खाली डिकट्स में समाप्त होती हैं":

 d1 = {'a': {1: {'foo': {}}, 2: {}}} d2 = {'a': {1: {}, 2: {'bar': {}}}} d3 = {'b': {3: {'baz': {}}}} d4 = {'a': {1: {'quux': {}}}} 

यह पुनरावर्ती के लिए सबसे सरल मामला है, और मैं दो भोले दृष्टिकोणों की सिफारिश करेगा:

 def rec_merge1(d1, d2): '''return new merged dict of dicts''' for k, v in d1.items(): # in Python 2, use .iteritems()! if k in d2: d2[k] = rec_merge1(v, d2[k]) d3 = d1.copy() d3.update(d2) return d3 def rec_merge2(d1, d2): '''update first dict with second recursively''' for k, v in d1.items(): # in Python 2, use .iteritems()! if k in d2: d2[k] = rec_merge2(v, d2[k]) d1.update(d2) return d1 

मेरा मानना ​​है कि मैं पहली बार दूसरे को पसंद करता हूं, लेकिन ध्यान रखें कि पहले की मूल स्थिति को इसके मूल से पुनर्निर्माण करना होगा। यहां उपयोग किया गया है:

 >>> from functools import reduce # only required for Python 3. >>> reduce(rec_merge1, (d1, d2, d3, d4)) {'a': {1: {'quux': {}, 'foo': {}}, 2: {'bar': {}}}, 'b': {3: {'baz': {}}}} >>> reduce(rec_merge2, (d1, d2, d3, d4)) {'a': {1: {'quux': {}, 'foo': {}}, 2: {'bar': {}}}, 'b': {3: {'baz': {}}}} 

जटिल मामला: "पत्तियां किसी अन्य प्रकार के हैं:"

इसलिए यदि वे नियमों में समाप्त हो जाते हैं, तो यह अंत खाली रिकॉर्ड्स मर्ज करने का एक सरल मामला है। यदि नहीं, तो यह इतना तुच्छ नहीं है अगर तार, आप उन्हें कैसे मर्ज करते हैं? समूह को इसी तरह अपडेट किया जा सकता है, इसलिए हम उस उपचार को दे सकते हैं, लेकिन हम उस क्रम को खो देते हैं जिसमें वे विलीन हो गए। तो क्या बात करता है?

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

 d1 = {'a': {1: 'foo', 2: None}} d2 = {'a': {1: None, 2: 'bar'}} d3 = {'b': {3: 'baz'}} d4 = {'a': {1: 'quux'}} from collections import MutableMapping def rec_merge(d1, d2): ''' Update two dicts of dicts recursively, if either mapping has leaves that are non-dicts, the second's leaf overwrites the first's. ''' for k, v in d1.items(): # in Python 2, use .iteritems()! if k in d2: # this next check is the only difference! if all(isinstance(e, MutableMapping) for e in (v, d2[k])): d2[k] = rec_merge(v, d2[k]) # we could further check types and merge as appropriate here. d3 = d1.copy() d3.update(d2) return d3 

और अब

 from functools import reduce reduce(rec_merge, (d1, d2, d3, d4)) 

रिटर्न

 {'a': {1: 'quux', 2: 'bar'}, 'b': {3: 'baz'}} 

मूल प्रश्न के लिए आवेदन:

मुझे पत्रों के चारों ओर घुंघराले ब्रेसिज़ को निकालना पड़ा और उन्हें एक ही उद्धरण में डालने के लिए कानूनी पायथन (अन्यथा वे पायथन 2.7+ में शाब्दिक सेट होंगे) के साथ ही एक लापता ब्रेस संलग्न करें:

 dict1 = {1:{"a":'A'}, 2:{"b":'B'}} dict2 = {2:{"c":'C'}, 3:{"d":'D'}} 

और rec_merge(dict1, dict2) अब रिटर्न:

 {1: {'a': 'A'}, 2: {'c': 'C', 'b': 'B'}, 3: {'d': 'D'}} 

कौन सा मूल प्रश्न के इच्छित परिणाम से मेल खाता है (बदलने के बाद, उदाहरण के लिए {A} से 'A' ।)

फ़ंक्शन का यह संस्करण N के शब्दकोशों के लिए खाता होगा, और केवल शब्दकोश – कोई अनुचित पैरामीटर पारित नहीं किया जा सकता है, या यह TypeError को बढ़ा देगा। मर्ज ही कुंजी टकराव के लिए है, और एक शब्दकोष से मर्ज श्रृंखला के नीचे डेटा को अधिलेखित करने के बजाय, यह मूल्यों का एक सेट बनाता है और उस पर लगाया जाता है; कोई डेटा खोया नहीं है

यह पृष्ठ पर सबसे अधिक प्रभावी नहीं हो सकता है, लेकिन यह सबसे अधिक संपूर्ण है और आप किसी भी जानकारी को खोने नहीं जा रहे हैं, जब आप अपने 2 से एन डिगर्ट्स को मर्ज करेंगे।

 def merge_dicts(*dicts): if not reduce(lambda x, y: isinstance(y, dict) and x, dicts, True): raise TypeError, "Object in *dicts not of type dict" if len(dicts) < 2: raise ValueError, "Requires 2 or more dict objects" def merge(a, b): for d in set(a.keys()).union(b.keys()): if d in a and d in b: if type(a[d]) == type(b[d]): if not isinstance(a[d], dict): ret = list({a[d], b[d]}) if len(ret) == 1: ret = ret[0] yield (d, sorted(ret)) else: yield (d, dict(merge(a[d], b[d]))) else: raise TypeError, "Conflicting key:value type assignment" elif d in a: yield (d, a[d]) elif d in b: yield (d, b[d]) else: raise KeyError return reduce(lambda x, y: dict(merge(x, y)), dicts[1:], dicts[0]) print merge_dicts({1:1,2:{1:2}},{1:2,2:{3:1}},{4:4}) 

आउटपुट: {1: [1, 2], 2: {1: 2, 3: 1}, 4: 4}

यह dict2 में dict1 से सभी वस्तुओं को मर्ज करने में मदद करनी चाहिए:

 for item in dict2: if item in dict1: for leaf in dict2[item]: dict1[item][leaf] = dict2[item][leaf] else: dict1[item] = dict2[item] 

कृपया इसे जांचें और हमें बताएं कि क्या यह वही है जो आप चाहते थे

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

उपर्युक्त समाधान केवल एक स्तर में विलीन हो जाता है, लेकिन ओपी द्वारा दिए गए उदाहरण को ठीक से हल करता है। कई स्तरों को मर्ज करने के लिए, रिकर्सन का उपयोग किया जाना चाहिए।

परस्पर विरोधी कुंजी को ओवरराइड करने के दौरान यह सरल पुनरावर्ती प्रक्रिया एक शब्दकोश में दूसरे में विलय करेगी:

 #!/usr/bin/env python2.7 def merge_dicts(dict1, dict2): """ Recursively merges dict2 into dict1 """ if not isinstance(dict1, dict) or not isinstance(dict2, dict): return dict2 for k in dict2: if k in dict1: dict1[k] = merge_dicts(dict1[k], dict2[k]) else: dict1[k] = dict2[k] return dict1 print (merge_dicts({1:{"a":"A"}, 2:{"b":"B"}}, {2:{"c":"C"}, 3:{"d":"D"}})) print (merge_dicts({1:{"a":"A"}, 2:{"b":"B"}}, {1:{"a":"A"}, 2:{"b":"C"}})) 

आउटपुट:

 {1: {'a': 'A'}, 2: {'c': 'C', 'b': 'B'}, 3: {'d': 'D'}} {1: {'a': 'A'}, 2: {'b': 'C'}} 

एंड्रयू कुकीज के साथ मामूली समस्या है: कुछ मामलों में यह दूसरी तर्क को संशोधित करता है जब आप लौटे हुए शब्द को संशोधित करते हैं। विशेष रूप से यह इस पंक्ति के कारण है:

 if key in a: ... else: a[key] = b[key] 

यदि b[key] एक शब्द है, तो यह केवल a को सौंपा जाएगा, जिसका अर्थ है कि किसी भी बाद के संशोधनों को उस शब्द को दोनों और b को प्रभावित होगा।

 a={} b={'1':{'2':'b'}} c={'1':{'3':'c'}} merge(merge(a,b), c) # {'1': {'3': 'c', '2': 'b'}} a # {'1': {'3': 'c', '2': 'b'}} (as expected) b # {'1': {'3': 'c', '2': 'b'}} <---- c # {'1': {'3': 'c'}} (unmodified) 

इसे ठीक करने के लिए, लाइन को इसके साथ प्रतिस्थापित करना होगा:

 if isinstance(b[key], dict): a[key] = clone_dict(b[key]) else: a[key] = b[key] 

जहां clone_dict है:

 def clone_dict(obj): clone = {} for key, value in obj.iteritems(): if isinstance(value, dict): clone[key] = clone_dict(value) else: clone[key] = value return 

फिर भी। यह स्पष्ट रूप से list , set और अन्य सामानों के लिए खाता नहीं है, लेकिन मुझे आशा है कि ये dicts को मर्ज करने की कोशिश करते समय नुकसान का वर्णन करता है।

और पूर्णता की खातिर, यहां मेरा संस्करण है, जहां आप इसे कई dicts को पारित कर सकते हैं:

 def merge_dicts(*args): def clone_dict(obj): clone = {} for key, value in obj.iteritems(): if isinstance(value, dict): clone[key] = clone_dict(value) else: clone[key] = value return def merge(a, b, path=[]): for key in b: if key in a: if isinstance(a[key], dict) and isinstance(b[key], dict): merge(a[key], b[key], path + [str(key)]) elif a[key] == b[key]: pass else: raise Exception('Conflict at `{path}\''.format(path='.'.join(path + [str(key)]))) else: if isinstance(b[key], dict): a[key] = clone_dict(b[key]) else: a[key] = b[key] return a return reduce(merge, args, {}) 

मेरे पास दो शब्दकोश ( a और b ) थे जिनमें प्रत्येक में नेस्टेड शब्दकोशों के किसी भी संख्या शामिल हो सकती थी मैं उन्हें पुन: प्रारंभिक रूप से विलय करना चाहता था, b साथ a पर प्राथमिकता लेना चाहता था।

पेड़ों के रूप में नेस्टेड शब्दकोशों को देखते हुए, जो मैं चाहता था वह था:

  • ऐसा अद्यतन करने के लिए कि प्रत्येक b को हर पथ के लिए प्रत्येक पथ को a में दर्शाया जाएगा
  • किसी के उप पथों को अधिलेखित करने के लिए अगर एक पत्ती इसी पथ में b में पाया जाता है
    • अपरिवर्तनीय बनाए रखें कि सभी b पत्ते के नोड्स पत्ते रहते हैं

मौजूदा उत्तर मेरे स्वाद के लिए थोड़ा जटिल थे और शेल्फ पर कुछ विवरण छोड़ दिए थे। मैं एक साथ नीचे hacked है, जो मेरे डेटा सेट के लिए यूनिट परीक्षण पास।

  def merge_map(a, b): if not isinstance(a, dict) or not isinstance(b, dict): return b for key in b.keys(): a[key] = merge_map(a[key], b[key]) if key in a else b[key] return a 

उदाहरण (स्पष्टता के लिए स्वरूपित):

  a = { 1 : {'a': 'red', 'b': {'blue': 'fish', 'yellow': 'bear' }, 'c': { 'orange': 'dog'}, }, 2 : {'d': 'green'}, 3: 'e' } b = { 1 : {'b': 'white'}, 2 : {'d': 'black'}, 3: 'e' } >>> merge_map(a, b) {1: {'a': 'red', 'b': 'white', 'c': {'orange': 'dog'},}, 2: {'d': 'black'}, 3: 'e'} 

बनाए रखने के लिए आवश्यक b में पथ थे:

  • 1 -> 'b' -> 'white'
  • 2 -> 'd' -> 'black'
  • 3 -> 'e'

a के अद्वितीय और गैर-विवादित पथ थे:

  • 1 -> 'a' -> 'red'
  • 1 -> 'c' -> 'orange' -> 'dog'

इसलिए वे अब भी मर्ज किए गए मानचित्र में प्रतिनिधित्व करते हैं।

यह कोड मर्ज ट्रिबल्स को हल करने के लिए आपके नियमों पर निर्भर करेगा, निश्चित रूप से। यहां एक ऐसा संस्करण है जो किसी भी मनमाने तरीके से तर्कों की संख्या ले सकता है और बिना किसी ऑब्जेक्ट उत्परिवर्तन के उपयोग के बिना एक मनमाना गहराई में उन्हें विलीन कर सकता है। मर्ज ट्रिबल्स को हल करने के लिए यह निम्नलिखित नियमों का उपयोग करता है:

  • शब्दकोशों को गैर-तेंदुए मूल्यों पर प्राथमिकता दी जाती है ( {"foo": {...}} {"foo": "bar"} पर पूर्वता लेता है)
  • बाद में बहस पहले तर्कों पर पूर्वता लेती हैं (यदि आप {"a": 1} , {"a", 2} , और {"a": 3} को क्रम में मर्ज करते हैं, तो परिणाम {"a": 3} )
 try: from collections import Mapping except ImportError: Mapping = dict def merge_dicts(*dicts): """ Return a new dictionary that is the result of merging the arguments together. In case of conflicts, later arguments take precedence over earlier arguments. """ updated = {} # grab all keys keys = set() for d in dicts: keys = keys.union(set(d)) for key in keys: values = [d[key] for d in dicts if key in d] # which ones are mapping types? (aka dict) maps = [value for value in values if isinstance(value, Mapping)] if maps: # if we have any mapping types, call recursively to merge them updated[key] = merge_dicts(*maps) else: # otherwise, just grab the last value we have, since later arguments # take precedence over earlier arguments updated[key] = values[-1] return updated 

मैं आपके समाधानों का परीक्षण कर रहा हूं और अपने प्रोजेक्ट में इसका उपयोग करने का निर्णय लिया है:

 def mergedicts(dict1, dict2, conflict, no_conflict): for k in set(dict1.keys()).union(dict2.keys()): if k in dict1 and k in dict2: yield (k, conflict(dict1[k], dict2[k])) elif k in dict1: yield (k, no_conflict(dict1[k])) else: yield (k, no_conflict(dict2[k])) dict1 = {1:{"a":"A"}, 2:{"b":"B"}} dict2 = {2:{"c":"C"}, 3:{"d":"D"}} #this helper function allows for recursion and the use of reduce def f2(x, y): return dict(mergedicts(x, y, f2, lambda x: x)) print dict(mergedicts(dict1, dict2, f2, lambda x: x)) print dict(reduce(f2, [dict1, dict2])) 

Parameteres के रूप में फ़ंक्शन पासिंग सभी अन्य रिकर्सिव समाधान के रूप में व्यवहार करने के लिए jterrace समाधान को बढ़ाने के लिए महत्वपूर्ण है।

सबसे आसान तरीका मैं सोच सकता हूँ:

 #!/usr/bin/python from copy import deepcopy def dict_merge(a, b): if not isinstance(b, dict): return b result = deepcopy(a) for k, v in b.iteritems(): if k in result and isinstance(result[k], dict): result[k] = dict_merge(result[k], v) else: result[k] = deepcopy(v) return result a = {1:{"a":'A'}, 2:{"b":'B'}} b = {2:{"c":'C'}, 3:{"d":'D'}} print dict_merge(a,b) 

आउटपुट:

 {1: {'a': 'A'}, 2: {'c': 'C', 'b': 'B'}, 3: {'d': 'D'}} 

चूंकि निर्देशों का समर्थन सेट ऑपरेशन है, इसलिए मैं जटर्रेस के उत्तर को बहुत सरल बनाने में सक्षम था।

 def merge(dict1, dict2): for k in dict1.keys() - dict2.keys(): yield (k, dict1[k]) for k in dict2.keys() - dict1.keys(): yield (k, dict2[k]) for k in dict1.keys() & dict2.keys(): yield (k, dict(merge(dict1[k], dict2[k]))) 

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

मेरे पास एक और थोड़ा अलग समाधान है:

 def deepMerge(d1, d2, inconflict = lambda v1,v2 : v2) : ''' merge d2 into d1. using inconflict function to resolve the leaf conflicts ''' for k in d2: if k in d1 : if isinstance(d1[k], dict) and isinstance(d2[k], dict) : deepMerge(d1[k], d2[k], inconflict) elif d1[k] != d2[k] : d1[k] = inconflict(d1[k], d2[k]) else : d1[k] = d2[k] return d1 

डिफ़ॉल्ट रूप से यह दूसरे सिद्धांत से मूल्यों के पक्ष में संघर्ष को हल करता है, लेकिन आप इसे आसानी से ओवरराइड कर सकते हैं, कुछ सुस्ती के साथ आप इसके बाहर अपवाद भी फेंक सकते हैं। :)।