2012-02-16 17 views
13

के साथ पाइथन dict तक पहुंचना मैं पाइथन में एक साधारण "लुकअप" तंत्र बनाना चाहता हूं, और यह सुनिश्चित करना चाहता था कि पाइथन में विशाल पुस्तकालयों में पहले से कहीं कुछ छिपा हुआ न हो जो पहले से नहीं करता इसे बनाने से पहले यह।एकाधिक कुंजी लुकअप स्ट्रिंग

मैं एक dict कि इस

my_dict = { 
    "root": { 
    "secondary": { 
     "user1": { 
      "name": "jim", 
      "age": 24 
     }, 
     "user2": { 
     "name": "fred", 
     "age": 25 
     } 
    } 
    } 
} 

की तरह कुछ स्वरूपित है लेने के लिए देख रहा हूँ और मैं एक दशमलव संकेतन कि

को कुछ इसी तरह होगा का उपयोग करके डेटा का उपयोग करने के लिए एक रास्ता है करने के लिए कोशिश कर रहा हूँ
root.secondary.user2 

और इसके परिणामस्वरूप प्रतिक्रिया के रूप में वापस निर्देशित किया गया। मैं सोच रहा हूं कि ऐसा कुछ होना चाहिए जो ऐसा करता है और मैं बिना किसी कठिनाई के एक लिख सकता हूं लेकिन मैं यह सुनिश्चित करना चाहता हूं कि मैं कुछ ऐसा नहीं कर रहा हूं जो मैं दस्तावेज से गायब हो सकता हूं। धन्यवाद

+0

क्या आप सिंटैक्टिक चीनी ('mydict.root.secondary.user2') की तलाश में हैं या सिर्फ स्ट्रिंग के माध्यम से देख रहे हैं? –

उत्तर

28

इस उद्देश्य के लिए मानक पुस्तकालय में कुछ भी नहीं है, लेकिन यह इस अपने आप को कोड करने के लिए नहीं बल्कि आसान है:

>>> key = "root.secondary.user2" 
>>> reduce(dict.get, key.split("."), my_dict) 
{'age': 25, 'name': 'fred'} 

इस तथ्य का शोषण करने वाली है कि कुंजी k में के लिए लुक-अप शब्दकोश ddict.get(d, k) के रूप में लिखा जा सकता है। इसे reduce() का उपयोग करके इसे लागू करने के लिए वांछित परिणाम की ओर जाता है।

संपादित: पूर्णता के लिए तीन कार्यों पाने के लिए, सेट या इस पद्धति का उपयोग कुंजी शब्दकोश हटाएँ:

def get_key(my_dict, key): 
    return reduce(dict.get, key.split("."), my_dict) 

def set_key(my_dict, key, value): 
    key = key.split(".") 
    my_dict = reduce(dict.get, key[:-1], my_dict) 
    my_dict[key[-1]] = value 

def del_key(my_dict, key): 
    key = key.split(".") 
    my_dict = reduce(dict.get, key[:-1], my_dict) 
    del my_dict[key[-1]] 
+0

यह पुनर्प्राप्त करने के लिए बहुत अच्छा काम करता है, लेकिन 'कम()' उत्तर के लिए उसी विधि – Tanerax

+0

+1 का उपयोग करके उस नियम में वास्तव में उस फ़ील्ड को अपडेट करने के बारे में कोई विचार; हालांकि मैं भी वास्तव में जवाब की तरह सादा हूं, इच्छा है कि मैं +2 कर सकता हूं। – SingleNegationElimination

+0

@ टैनरेक्स: अद्यतन करने के लिए, कुंजी के अंतिम घटक को विभाजित करें और प्रमुख घटकों का उपयोग करके युक्त शब्दकोश को पुनर्प्राप्त करें। उत्तर में उदाहरण कोड जोड़ा गया। –

1

Recursion अभी भी काम करता है।

def walk_into(dict, key): 
    head, _, tail = key.partition('.') 
    if tail: 
     return walk_into(dict[head], tail) 
    return dict, key 
d, k = walk_into(my_dict, "root.secondary.user2") 

d[k] का उपयोग नए मूल्य को प्राप्त करने या रखने के लिए किया जा सकता है।

2

आपके पास यह हो सकता है। आप नीचे दिए गए कोड के समान कोड का उपयोग कर, कुंजी को देख सकते हैं, कुंजी लुकअप (और यहां तक ​​कि नाम निर्देश भी बनाए रखें) जोड़ सकते हैं। {...} फॉर्म अभी भी बिल्टिन डॉक क्लास (जिसे अब orig_dict कहा जाता है) का उपयोग करेगा, इसलिए आपको इसे संलग्न करना होगा, जैसे: Dict({...})। यह कार्यान्वयन बार-बार शब्दकोशों को नए रूप में परिवर्तित करता है, इसलिए आपको उपरोक्त विधि का उपयोग किसी भी शब्दकोश प्रविष्टि के लिए नहीं करना है जो सादे शब्दकोश हैं।

orig_dict = dict 
class Dict(orig_dict): 
    def __init__(self, *args, **kwargs): 
     super(Dict, self).__init__(*args, **kwargs) 
     for k, v in self.iteritems(): 
      if type(v) == orig_dict and not isinstance(v, Dict): 
       super(Dict, self).__setitem__(k, Dict(v)) 
    def __getattribute__(self, k): 
     try: return super(Dict, self).__getattribute__(k) 
     except: return self.__getitem__(k) 
    def __setattr__(self, k, v): 
     if self.has_key(k): self.__setitem__(k, v) 
     else: return super(Dict, self).__setattr__(k, v) 
    def __delattr__(self, k): 
     try: self.__delitem__(k) 
     except: super(Dict, self).__delattr__(k) 
    def __setitem__(self, k, v): 
     toconvert = type(v) == orig_dict and not isinstance(v, Dict) 
     super(Dict, self).__setitem__(k, Dict(v) if toconvert else v) 

# dict = Dict <-- you can even do this but I advise against it 

# testing: 
b = Dict(a=1, b=Dict(c=2, d=3)) 
c = Dict({'a': 1, 'b': {'c': 2, 'd': 3}}) 
d = Dict(a=1, b={'c': 2, 'd': {'e': 3, 'f': {'g': 4}}}) 

b.a = b.b 
b.b = 1 
d.b.d.f.g = 40 
del d.b.d.e 
d.b.c += d.b.d.f.g 
c.b.c += c.a 
del c.a 
print b 
print c 
print d 
संबंधित मुद्दे