2014-07-22 7 views
7

सामान्य मामले में हम नेस्टेड डाइकों की रिकर्सिव पहुंच कैसे कर सकते हैं?पुनरावर्ती घोंसला वाले हथियार तक पहुंचने का पाइथोनिक तरीका

from collections import defaultdict 

D = lambda: defaultdict(D) 
d = D() 

keys = ['k1', 'k2', 'k3'] 
value = 'v' 

if len(keys) == 3: 
    k1, k2, k3 = keys 
    d[k1][k2][k3] = value 
else: 
    ??? 

मैं reduce, d.__getitem__ और d.__setitem__ के कुछ भयानक पथ नीचे जा रहा था, लेकिन महसूस किया वहाँ निश्चित रूप से एक और अधिक सुरुचिपूर्ण तरीका होना चाहिए ...

+0

अच्छी खोज @ डेव। आपकी खोज अलगो एसओ की संबंधित प्रश्नों की खोज से बेहतर है। – Gerrat

+0

वास्तव में अच्छा लगता है। डुप्लिकेट के रूप में अपना खुद का प्रश्न बंद कर रहा है ... :) – wim

उत्तर

3

यह बहुत बदसूरत है, लेकिन यह काम करता है:

def set_val(d, keys, val): 
    reduce(lambda x,y: x[y], keys[:-1], d)[keys[-1]] = val 

थोड़ा अधिक पठनीय संस्करण:

def set_val(d, keys, val): 
    last = keys[-1] # Key we want to set val on 
    search_keys = keys[:-1] # Keys we need to traverse 
    reduce(lambda x,y: x[y], search_keys, d)[last] = val 

उपयोग:

>>> from collections import defaultdict 
>>> D = lambda: defaultdict(D) 
>>> d = D() 
>>> set_val(d, ['k1', 'k2', 'k3'], "hi") 
>>> d 
defaultdict(<function <lambda> at 0x7fbd365ac7d0>, {'k1': defaultdict(<function <lambda> at 0x7fbd365ac7d0>, {'k2': defaultdict(<function <lambda> at 0x7fbd365ac7d0>, {'k3': 'hi'})})}) 
>>> d['k1']['k2']['k3'] 
'hi' 

यह reduce का उपयोग करता भीतरी सबसे dict का अनुरोध किया (keys[:-1]) तक पहुँचने के लिए है, तो वांछित मान (output_of_reduce[keys[-1]] = val) के लिए सूची में अंतिम कुंजी सेट करता है।

ध्यान दें कि पायथन 3 में आपको इसका उपयोग करने के लिए functools import reduce से एक की आवश्यकता होगी।

def set_val(d, keys, val): 
    out = d 
    for k in keys[:-1]: 
     out = out[k] 
    out[keys[-1]] = val 
+0

यह काम करता है, लेकिन मुझे उम्मीद है कि एक और सुरुचिपूर्ण विचार है .. – wim

2

तुम बस प्रत्यावर्तन इस्तेमाल कर सकते हैं:

यहाँ स्पष्टता के लिए विस्तार किया कोड है। लूपिंग की तुलना में इसे और अधिक सुरुचिपूर्ण या अधिक पायथनिक नहीं कह सकता है, या हालांकि कम करने का उपयोग कर सकते हैं।

def assign(dct, keylist, value): 
    if not keylist: 
     dct = value 
    else: 
     dct[keylist[0]] = assign(dct[keylist[0]], keylist[1:], value) 
    return dct 


if __name__ == '__main__': 
    from collections import defaultdict 
    D = lambda: defaultdict(D) 
    d = D() 
    keys = ['k1', 'k2', 'k3'] 
    value = 'v' 
    assign(d, keys, value) 
    print d['k1']['k2']['k3'] 

[prints] 'v' 
संबंधित मुद्दे