कैसे एक ही कुंजी के साथ कई dicts विलय करने के लिए?


88

मेरे पास इस तरह के कई डाइक / की-वैल्यू जोड़े हैं:

d1 = {key1: x1, key2: y1}  
d2 = {key1: x2, key2: y2}  

मैं चाहता हूं कि परिणाम एक नया हो (सबसे कुशल तरीके से, यदि संभव हो तो):

d = {key1: (x1, x2), key2: (y1, y2)}  

वास्तव में, मैं परिणाम d होना चाहता हूं:

d = {key1: (x1.x1attrib, x2.x2attrib), key2: (y1.y1attrib, y2.y2attrib)}  

यदि कोई मुझे दिखाता है कि पहला परिणाम कैसे प्राप्त किया जाए, तो मैं बाकी का पता लगा सकता हूं।


4
@ शैल: क्या हम मान सकते हैं कि प्रत्येक कुंजी सभी शब्दकोशों में मौजूद है?
ब्योर्न पोलेक्स


हाय Space_C0wb0y, हाँ, सभी शब्दकोशों में कुंजियाँ मौजूद हैं।
सलिल

यह निर्दिष्ट करना बिल्कुल महत्वपूर्ण है कि क्या सभी डाइक में एक ही कुंजी है।
युग

जवाबों:


46

सभी कुंजियों में सभी कुंजियाँ हमेशा मौजूद होती हैं:

ds = [d1, d2]
d = {}
for k in d1.iterkeys():
    d[k] = tuple(d[k] for d in ds)

नोट: पायथन 3.x में कोड के नीचे उपयोग:

ds = [d1, d2]
d = {}
for k in d1.keys():
  d[k] = tuple(d[k] for d in ds)

और यदि dic में सुन्न सरणियाँ हों:

ds = [d1, d2]
d = {}
for k in d1.keys():
  d[k] = np.concatenate(list(d[k] for d in ds))

3
बस "के लिए डी 1 में" क्या मुझे लगता है।
सलिल

और d.get (k, कोई नहीं) के स्थान पर d [k]
ताहिर

1
@ तहरीर का मतलब यह होगा कि डिकेट्स में गैर-मिलान कुंजी है इसलिए ओवररेट करना d1सही नहीं है (यह अन्य डाइक में कुंजियों को याद कर सकता है)।
युग

1
अजगर 3 उपयोगकर्ताओं के लिए: d1.iterkeys () = d1.items ()
रिले

यह अभी भी Python3.x में मेरे लिए काम नहीं करता है। मैंने यह कोशिश की है, भले ही मेरे मूल्य सरणियाँ नहीं हैं, और यह काम करता है। हालाँकि, मान आउटपुट सरणियाँ होगी। stackoverflow.com/questions/54040858/…
रिक एस

74

यहां एक सामान्य समाधान है जो शब्दकोशों की एक मनमानी मात्रा को संभालेंगे, ऐसे मामलों में जब चाबियाँ केवल कुछ शब्दकोशों में हैं:

from collections import defaultdict

d1 = {1: 2, 3: 4}
d2 = {1: 6, 3: 7}

dd = defaultdict(list)

for d in (d1, d2): # you can list as many input dicts as you want here
    for key, value in d.items():
        dd[key].append(value)

print(dd)

दिखाता है:

defaultdict(<type 'list'>, {1: [2, 6], 3: [4, 7]})

इसके अलावा, अपने पाने के लिए .attrib, बस append(value)करने के लिए बदल जाते हैंappend(value.attrib)


मैं ओ पी के रूप में मान चाहता है tupleनहीं list
user225312

1
@ एए: क्या यह वास्तव में मायने रखता है? कई इनपुट डाइक के सामान्य मामले में ट्यूपल्स बनाने के लिए और अधिक मुश्किल होगा, जहां कुछ चाबियाँ हर जगह मौजूद नहीं हैं, imho
एली बेन्द्स्की

1
तो आप एक सामान्य बनाने के लिए चाहते हो सकता है dictसे बाहर defaultdictताकि आप सामान्य है dictन के बराबर चाबी के लिए व्यवहार आदि: dd = dict(dd)
नेड Deily

@ नीड: अच्छी बात है, लेकिन यह डेटा के अंतिम उपयोग पर निर्भर करता है
एली बेंडस्की

@ एली: नहीं, इससे कोई फर्क नहीं पड़ता, लेकिन मैं इसे ओपी के लिए जो चाह रहा था, उसे आधार देने की कोशिश कर रहा था और उम्मीद कर रहा था कि आप से
टुपल्स के

4

यदि आपके पास केवल d1 और d2 हैं,

from collections import defaultdict

d = defaultdict(list)
for a, b in d1.items() + d2.items():
    d[a].append(b)

4

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

d1 = {'a':'test','b':'btest','d':'dreg'}
d2 = {'a':'cool','b':'main','c':'clear'}

d = {}

for key in set(d1.keys() + d2.keys()):
    try:
        d.setdefault(key,[]).append(d1[key])        
    except KeyError:
        pass

    try:
        d.setdefault(key,[]).append(d2[key])          
    except KeyError:
        pass

print d

यह नीचे इनपुट उत्पन्न करेगा:

{'a': ['test', 'cool'], 'c': ['clear'], 'b': ['btest', 'main'], 'd': ['dreg']}

उत्तर में set(d1.keys() + d2.keys()) बदला जा सकता है set(list(d1.keys()) + list(d2.keys()))(अजगर 3.x के लिए)? अन्यथा यह TypeError: unsupported operand type(s) for +: 'dict_keys' and 'dict_keys'python3.x
R4444

4
dict1 = {'m': 2, 'n': 4}
dict2 = {'n': 3, 'm': 1}

यह सुनिश्चित करना कि कुंजियाँ उसी क्रम में हैं:

dict2_sorted = {i:dict2[i] for i in dict1.keys()}

keys = dict1.keys()
values = zip(dict1.values(), dict2_sorted.values())
dictionary = dict(zip(keys, values))

देता है:

{'m': (2, 1), 'n': (4, 3)}

2
तत्वों का क्रम values()अपरिभाषित है, इसलिए आप असंबंधित कुंजियों से मूल्यों का विलय कर सकते हैं।
युग

मैंने अभी बदलावों को लागू किया है इसलिए यह अब आपकी प्रतिक्रिया पर कब्जा कर सकता है
Mahdi Ghelichi

मुझे नहीं लगता कि परिवर्तन समस्या को ठीक करेगा। आपको पूर्वानुमानित परिणामों को प्राप्त करने sorted(d.items())या उपयोग करने की आवश्यकता है sorted(d.keys())
युग

क्या आप एक उदाहरण दे सकते हैं जो इसे अन्यथा साबित करे। dict2_sorted अजगर में एक सॉर्ट किया गया शब्दकोश है!
महदी घालिची

1
मैंने इस पर एक छोटा शोध किया। पायथन (3.6+) के हाल के संस्करणों में पुनरावृत्ति क्रम से मिलान क्रम शुरू हुआ (उदाहरण के लिए यहां देखें ) जो आपके कोड को पास करता है। लेकिन इसे एक कार्यान्वयन विवरण माना जाता है, जिस पर भरोसा नहीं किया जाना चाहिए। मेरा दूसरा उदाहरण ( यहां देखें ) मज़बूती से ऑनलाइनगडब में विफल रहता है जो पुराने पायथन 3.4 का उपयोग करता है। अन्य ऑनलाइन दुभाषिए नए पायथन का उपयोग करते हैं इसलिए इस मुद्दे को वहां पुन: प्रस्तुत नहीं किया जा सकता है।
15

2

यह फ़ंक्शन दो डिस्क्स को मर्ज करता है, भले ही दो शब्दकोशों में कुंजियाँ अलग हों:

def combine_dict(d1, d2):
    combined = {}
    for k in set(d1.keys()) | set(d2.keys()):
        combined[k] = tuple(d[k] for d in [d1, d2] if k in d)
    return combined

उदाहरण:

d1 = {
    'a': 1,
    'b': 2,
}
d2` = {
    'b': 'boat',
    'c': 'car',
}
combine_dict(d1, d2)
# Returns: {
#    'a': (1,),
#    'b': (2, 'boat'),
#    'c': ('car',)
# }

1

पायथन 3.x अपडेट

एली Bendersky जवाब से:

अजगर 3 ने तानाशाही को हटा दिया। पायथन विकी देखें: https://wiki.python.org/moin/Python3.0

from collections import defaultdict

dd = defaultdict(list)

for d in (d1, d2):
    for key, value in d.items():
        dd[key].append(value)

1

मान लें कि आपके पास सभी कुंजियों की सूची है (आप सभी शब्दकोशों के माध्यम से पुनरावृत्ति करके और उनकी कुंजी प्राप्त कर सकते हैं)। नाम बताइए listKeys। इसके अलावा:

  • listValues एक कुंजी के लिए सभी मानों की सूची है जिसे आप मर्ज करना चाहते हैं।
  • allDicts: सभी शब्दकोष जिन्हें आप मर्ज करना चाहते हैं।
result = {}
for k in listKeys:
    listValues = [] #we will convert it to tuple later, if you want.
    for d in allDicts:
       try:
            fileList.append(d[k]) #try to append more values to a single key
        except:
            pass
    if listValues: #if it is not empty
        result[k] = typle(listValues) #convert to tuple, add to new dictionary with key k

0
def merge(d1, d2, merge):
    result = dict(d1)
    for k,v in d2.iteritems():
        if k in result:
            result[k] = merge(result[k], v)
        else:
            result[k] = v
    return result

d1 = {'a': 1, 'b': 2}
d2 = {'a': 1, 'b': 3, 'c': 2}
print merge(d1, d2, lambda x, y:(x,y))

{'a': (1, 1), 'c': 2, 'b': (2, 3)}

0

दो-सूची समाधानों के पूरक के लिए, यहां एकल सूची प्रसंस्करण के लिए एक समाधान है ।

एक नमूना सूची (नेटवर्क-संबंधी; मैन्युअल रूप से पठनीयता के लिए यहाँ स्वरूपित):

ec_num_list = [((src, tgt), ec_num['ec_num']) for src, tgt, ec_num in G.edges(data=True)]

print('\nec_num_list:\n{}'.format(ec_num_list))
ec_num_list:
[((82, 433), '1.1.1.1'),
  ((82, 433), '1.1.1.2'),
  ((22, 182), '1.1.1.27'),
  ((22, 3785), '1.2.4.1'),
  ((22, 36), '6.4.1.1'),
  ((145, 36), '1.1.1.37'),
  ((36, 154), '2.3.3.1'),
  ((36, 154), '2.3.3.8'),
  ((36, 72), '4.1.1.32'),
  ...] 

समान किनारों (टुपल्स द्वारा परिभाषित) के लिए डुप्लिकेट मानों पर ध्यान दें। उन "मूल्यों" को उनके संबंधित "कुंजी" से टकराने के लिए:

from collections import defaultdict
ec_num_collection = defaultdict(list)
for k, v in ec_num_list:
    ec_num_collection[k].append(v)

print('\nec_num_collection:\n{}'.format(ec_num_collection.items()))
ec_num_collection:
[((82, 433), ['1.1.1.1', '1.1.1.2']),   ## << grouped "values"
((22, 182), ['1.1.1.27']),
((22, 3785), ['1.2.4.1']),
((22, 36), ['6.4.1.1']),
((145, 36), ['1.1.1.37']),
((36, 154), ['2.3.3.1', '2.3.3.8']),    ## << grouped "values"
((36, 72), ['4.1.1.32']),
...] 

यदि आवश्यक हो, तो उस सूची को तानाशाही में बदल दें:

ec_num_collection_dict = {k:v for k, v in zip(ec_num_collection, ec_num_collection)}

print('\nec_num_collection_dict:\n{}'.format(dict(ec_num_collection)))
  ec_num_collection_dict:
  {(82, 433): ['1.1.1.1', '1.1.1.2'],
  (22, 182): ['1.1.1.27'],
  (22, 3785): ['1.2.4.1'],
  (22, 36): ['6.4.1.1'],
  (145, 36): ['1.1.1.37'],
  (36, 154): ['2.3.3.1', '2.3.3.8'],
  (36, 72): ['4.1.1.32'],
  ...}

संदर्भ


0

ठग जवाब से:

आप प्रत्येक सूची से मानों का उपयोग करके सीधे टूपल भी बना सकते हैं

ds = [d1, d2]
d = {}
for k in d1.keys():
  d[k] = (d1[k], d2[k])

यह उपयोगी हो सकता है यदि आपके पास अपने टुपल्स के लिए एक विशिष्ट आदेश है

ds = [d1, d2, d3, d4]
d = {}
for k in d1.keys():
  d[k] = (d3[k], d1[k], d4[k], d2[k]) #if you wanted tuple in order of d3, d1, d4, d2

0

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

https://pypi.org/project/deepmerge/

from deepmerge import always_merger

def process_parms(args):
    temp_list = []
    for x in args:
        with open(x, 'r') as stream:
            temp_list.append(yaml.safe_load(stream))

    return always_merger.merge(*temp_list)

0

यदि कुंजी नेस्टेड हैं:

d1 = { 'key1': { 'nkey1': 'x1' }, 'key2': { 'nkey2': 'y1' } } 
d2 = { 'key1': { 'nkey1': 'x2' }, 'key2': { 'nkey2': 'y2' } }
ds = [d1, d2]
d = {}
for k in d1.keys():
    for k2 in d1[k].keys():
        d.setdefault(k, {})
        d[k].setdefault(k2, [])
        d[k][k2] = tuple(d[k][k2] for d in ds)

पैदावार:

{'key1': {'nkey1': ('x1', 'x2')}, 'key2': {'nkey2': ('y1', 'y2')}}

-4

एक कॉम्पैक्ट संभावना

d1={'a':1,'b':2}
d2={'c':3,'d':4}
context={**d1, **d2}
context
{'b': 2, 'c': 3, 'd': 4, 'a': 1}

सवाल एक ही कुंजी के साथ dicts विलय के बारे में है। आपका आवश्यक उत्तर नहीं है।
Pbd
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.