मैं पायथन में शब्दकोशों को एक साथ कैसे मिलाऊँ?


91
d3 = dict(d1, **d2)

मैं समझता हूं कि इससे शब्दकोश विलीन हो जाता है। लेकिन, क्या यह अद्वितीय है? क्या होगा अगर d1 में d2 लेकिन अलग-अलग मूल्य के समान कुंजी है? मैं चाहूंगा कि d1 और d2 को विलय कर दिया जाए, लेकिन डुप्लिकेट कुंजी होने पर d1 की प्राथमिकता है।


9
कृपया ध्यान रखें कि इस चाल को **कीवर्ड तर्क के दुरुपयोग माना जाता है जब तक कि सभी कुंजी d2स्ट्रिंग नहीं हैं। यदि सभी कुंजी d2तार नहीं हैं, तो यह पायथन 3.2 में विफल रहता है, और अजगर के वैकल्पिक कार्यान्वयन में जैसे कि अजगर, आयरनपिथॉन और पायपी। उदाहरण के लिए, mail.python.org/pipermail/python-dev/2010-April/099459.html देखें ।
मार्क डिकिंसन

जवाबों:


154

.update()यदि आपको मूल की आवश्यकता नहीं है तो आप इस विधि का उपयोग कर सकते हैं d2:

मौजूदा कुंजियों को अधिलेखित करते हुए अन्य से कुंजी / मान जोड़े के साथ शब्दकोश को अपडेट करें । वापसी None

उदाहरण के लिए:

>>> d1 = {'a': 1, 'b': 2} 
>>> d2 = {'b': 1, 'c': 3}
>>> d2.update(d1)
>>> d2
{'a': 1, 'c': 3, 'b': 2}

अपडेट करें:

निश्चित रूप से आप नए मर्ज किए गए बनाने के लिए पहले शब्दकोश को कॉपी कर सकते हैं। यह आवश्यक हो सकता है या नहीं भी हो सकता है। यदि आपके पास यौगिक शब्द हैं (ऐसी वस्तुएँ जिनमें अन्य वस्तुएँ हैं, जैसे सूचियाँ या वर्ग उदाहरण), तो आपके शब्दकोश में copy.deepcopyभी विचार किया जाना चाहिए।


1
इस मामले के साथ d1 तत्वों को सही ढंग से प्राथमिकता मिलनी चाहिए अगर परस्पर विरोधी कुंजी मिल जाए
ट्रे हुनर

मामले में आपको अभी भी इसकी आवश्यकता है, बस एक प्रतिलिपि बनाएं। d3 = d2.copy () d3.update (d1) लेकिन मैं d1 + d2 को भाषा में जोड़ा जाना चाहूंगा।
Stach

4
d1 + d2 समस्याग्रस्त है क्योंकि एक शब्दकोश में संघर्ष के दौरान प्राथमिकता होती है, और यह विशेष रूप से स्पष्ट नहीं है कि कौन सा है।
rjh

d1 + d2 केवल तभी लागू किया जाएगा जब पायथन मल्टीमप हासिल करता है, अन्यथा उपयोगकर्ता के लिए अस्पष्टता 8 बाइट टाइपिंग लाभ के लिए बहुत भ्रामक है।
निक बैस्टिन

आपके पास इस उदाहरण में शब्दकोष हैं: isinstance(int, object) is Trueअभी तक deepcopyआवश्यक नहीं लगता है।
एंटनी हैचकिंस

43

पायथन 2 में,

d1={'a':1,'b':2}
d2={'a':10,'c':3}

डी 1 ओवरराइड डी 2:

dict(d2,**d1)
# {'a': 1, 'c': 3, 'b': 2}

डी 2 ओवरराइड डी 1:

dict(d1,**d2)
# {'a': 10, 'c': 3, 'b': 2}

यह व्यवहार केवल कार्यान्वयन का एक झूठा नहीं है; यह प्रलेखन में गारंटी है :

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


3
पायथन 3.2 में आपके उदाहरण विफल हो जाएंगे (टाइप टाइप) का निर्माण, और ज्यथन, पाइपी और आयरनपिथॉन के वर्तमान संस्करणों में: पायथन के उन संस्करणों के लिए, जब **संकेतन के साथ एक तानाशाही गुजरती है, तो उस तानाशाह की सभी चाबियाँ तार होनी चाहिए। अधिक के लिए mail.python.org/pipermail/python-dev/2010-April/099427.html पर शुरू होने वाले अजगर-देव सूत्र को देखें ।
मार्क डिकिंसन

@ मर्क: सिर के लिए धन्यवाद। मैंने गैर-CPython कार्यान्वयन के साथ इसे संगत बनाने के लिए कोड को संपादित किया है।
अनटुब

3
यह विफल रहता है अगर आपकी चाबियाँ तार और संख्याओं के ट्यूपल्स हैं। उदाहरण के लिए। d1 = {(1, 'a'): 1, (1, 'b'): 0,} d2 = {(1, 'a'): 1, (2, 'b'): 2, (2) 'a'): 1,}
MySchizoBuddy

अनपैकिंग सिंटैक्स के बारे में, अजगर 3.5 में आने वाले परिवर्तनों के लिए इस पोस्ट को देखें ।
Ioannis Filippidis

मैं यह कहने जा रहा था कि d = dict(**d1, **d2)काम करता है, लेकिन यह उनकी टिप्पणी में @IoannisFilippidis संदर्भ है। शायद यहाँ स्निपेट भी शामिल हो गया है, इसलिए यह स्पष्ट है।
dwanderson 21

14

यदि आप d1संघर्षों में प्राथमिकता चाहते हैं , तो करें:

d3 = d2.copy()
d3.update(d1)

अन्यथा, रिवर्स d2और d1


1

मेरा समाधान एक मर्ज फ़ंक्शन को परिभाषित करना है। यह परिष्कृत नहीं है और सिर्फ एक लाइन की लागत है। यहाँ पायथन 3 में कोड है।

from functools import reduce
from operator import or_

def merge(*dicts):
    return { k: reduce(lambda d, x: x.get(k, d), dicts, None) for k in reduce(or_, map(lambda x: x.keys(), dicts), set()) }

टेस्ट

>>> d = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> d_letters = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d, d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d_letters, d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge(d)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> merge(d_letters)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z', 26: 'A', 27: 'B', 28: 'C', 29: 'D', 30: 'E', 31: 'F', 32: 'G', 33: 'H', 34: 'I', 35: 'J', 36: 'K', 37: 'L', 38: 'M', 39: 'N', 40: 'O', 41: 'P', 42: 'Q', 43: 'R', 44: 'S', 45: 'T', 46: 'U', 47: 'V', 48: 'W', 49: 'X', 50: 'Y', 51: 'Z'}
>>> merge()
{}

यह डिक्शनरी की मनमानी संख्या के लिए काम करता है। क्या उन डिक्शनरी में कोई डुप्लिकेट कुंजियाँ थीं, तर्क सूची में सबसे सही डिक्शनरी में से कुंजी जीतती है।


1
.updateइसमें कॉल के साथ एक साधारण लूप ( merged={}इसके बाद for d in dict: merged.update(d)) छोटा, अधिक पठनीय और अधिक कुशल होगा।
मार्क डिकिन्सन

1
या यदि आप वास्तव में उपयोग करना चाहते हैं reduceऔर lambdaएस, कैसे के बारे में return reduce(lambda x, y: x.update(y) or x, dicts, {})?
मार्क डिकिन्सन

1
आप अपने कोड को शेल में आज़मा सकते हैं और देख सकते हैं कि क्या यह सही है। मैं जो करने की कोशिश कर रहा था वह एक फ़ंक्शन लिखने के लिए है जो एक ही कार्यक्षमता के साथ विभिन्न प्रकार के शब्दकोश तर्क ले सकता है। बेहतर है कि लैम्ब्डा के नीचे x.update (y) का उपयोग न करें, क्योंकि यह हमेशा कोई नहीं लौटाता है । और मैं एक और सामान्य फ़ंक्शन मर्ज_विथ लिखने की कोशिश कर रहा हूं जो विभिन्न प्रकार के शब्दकोश तर्क देता है और आपूर्ति की गई फ़ंक्शन के साथ डुप्लिकेट कुंजियों से निपटता है। एक बार जब मैं किया जाता है, तो मैं इसे एक और धागे में पोस्ट करूंगा, जहां समाधान अधिक प्रासंगिक है।
लेई झाओ

यहाँ लिंक है जहाँ मैंने अधिक सामान्य समाधान लिखा है। आपका स्वागत है और एक नज़र है।
लेई झाओ


1

में शुरू Python 3.9, ऑपरेटर |दो शब्दकोशों से मर्ज किए गए कुंजी और मूल्यों के साथ एक नया शब्दकोश बनाता है:

# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d3 = d2 | d1
# d3: {'b': 2, 'c': 3, 'a': 1}

यह:

D2 और d1 के मर्ज किए गए कुंजी और मूल्यों के साथ एक नया शब्दकोश d3 बनाता है। जब d2 और d1 शेयर कुंजियाँ होती हैं तो d1 के मूल्य प्राथमिकता लेते हैं।


यह भी ध्यान दें कि |=d1 में प्राथमिकता के साथ, d1 को मर्ज करके d2 को संशोधित करता है:

# d1 = { 'a': 1, 'b': 2 }
# d2 = { 'b': 1, 'c': 3 }
d2 |= d1
# d2: {'b': 2, 'c': 3, 'a': 1}


0

मेरा मानना ​​है कि, जैसा कि ऊपर कहा गया है, का उपयोग d2.update(d1)करना सबसे अच्छा तरीका है और आप इसे कॉपी भी कर सकते हैंd2 पहले यदि आपको अभी भी इसकी आवश्यकता है।

यद्यपि, मैं dict(d1, **d2)यह बताना चाहता हूं कि वास्तव में सामान्य रूप से डिक्शनरीज़ को मर्ज करने का एक बुरा तरीका है क्योंकि कीवर्ड तर्क को तार होने की आवश्यकता है, इस प्रकार यह विफल हो जाएगा यदि आपके पास dictऐसा है:

{
  1: 'foo',
  2: 'bar'
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.