2012-07-28 12 views
8

मेरे पास एक शब्दकोश है जिसमें शब्दकोश शामिल हैं, जिनमें शब्दकोश भी हो सकते हैं, उदा।पायथन - शब्दकोशों के भीतर घोंसले मूल्यों तक पहुंच

dictionary = {'ID': 0001, 'Name': 'made up name', 'Transactions': 
       {'Transaction Ref': 'a1', 'Transaction Details': 
        {'Bill To': 'abc', 'Ship To': 'def', 'Product': 'Widget A' 
         ...} ...} ... } 

वर्तमान में मैं आईडी 001 के लिए 'विधेयक के लिए' पाने के लिए खोल रहा हूँ, 'लेनदेन रेफरी' a1 इस प्रकार है:

if dictionary['ID'] == 001: 
    transactions = dictionary['Transactions'] 
     if transactions['Transaction Ref'] == 'a1': 
      transaction_details = transactions['Transaction Details'] 
      bill_to = transaction_details['Bill To'] 

मैं मदद नहीं कर सकता लेकिन लगता है कि यह है एक छोटे से है भद्दा, विशेष रूप से अंतिम दो पंक्तियों - मैं निम्नलिखित की तर्ज पर कुछ की तरह महसूस काम करना चाहिए:

bill_to = transactions['Transaction Details']['Bill To'] 

वहाँ नेस्टेड शब्दकोशों में गहरे उतर इंटर में खोल के बिना के लिए एक सरल तरीका है मैं चर?

+6

लाइन यदि आपको लगता है कि वास्तव में काम करना चाहिए करता है। –

उत्तर

13
bill_to = transactions['Transaction Details']['Bill To'] 

वास्तव में काम करता है। transactions['Transaction Details'] एक अभिव्यक्ति है जो dict को दर्शाती है, ताकि आप इसमें लुकअप कर सकें। व्यावहारिक कार्यक्रमों के लिए, हालांकि, मैं नेस्टेड डिक्ट्स के लिए ओओ दृष्टिकोण पसंद करूंगा। collections.namedtuple विशेष रूप से कक्षाओं का एक समूह स्थापित करने के लिए उपयोगी है जिसमें केवल डेटा होता है (और स्वयं का कोई व्यवहार नहीं)।

वहाँ एक चेतावनी है: कुछ सेटिंग्स में, आप जब लुकअप कर KeyError को पकड़ने के लिए चाहते हो सकता है, और यह सेटिंग, वह भी काम करता है, यह बताने के लिए जो शब्दकोश लुकअप विफल मुश्किल है:

try: 
    bill_to = transactions['Transaction Details']['Bill To'] 
except KeyError: 
    # which of the two lookups failed? 
    # we don't know unless we inspect the exception; 
    # but it's easier to do the lookup and error handling in two steps 
+0

अविश्वसनीय रूप से सहायक - बहुत धन्यवाद! – user1530213

20

आप उपयोग कर सकते हैं कुछ इस तरह:

:

>>> def lookup(dic, key, *keys): 
...  if keys: 
...   return lookup(dic.get(key, {}), *keys) 
...  return dic.get(key) 
... 
>>> d = {'a':{'b':{'c':5}}} 
>>> print lookup(d, 'a', 'b', 'c') 
5 
>>> print lookup(d, 'a', 'c') 
None 

ही, यदि आप अलग-अलग पैरामीटर के रूप में अपनी खोज कुंजी परिभाषित करने के लिए नहीं करना चाहते हैं, तो आप सिर्फ उन में इस प्रकार की सूची के रूप में पारित कर सकते हैं

>>> print lookup(d, *['a', 'b', 'c']) 
5 
>>> print lookup(d, *['a', 'c']) 
None 
+0

मुझे आशा है कि आपको कोई फर्क नहीं पड़ता, मैंने इस फ़ंक्शन की वास्तविक गतिशील खोज क्षमता को स्पष्ट करने के लिए एक संपादन जोड़ा। ऑन-द-फ्लाई पर खोज कुंजी की सूची में पास करने की क्षमता अन्य तकनीकों के ऊपर एक कट बनाती है। –

2

बाद नेस्टेड शब्दकोशों

>>> dbo={'m':{'d':{'v':{'version':1}}}} 
>>> name='m__d__v__version' # it'll refer to 'dbo['m']['d']['v']['version']', '__' is the separator 
>>> version = reduce(dict.get, name.split('__'), dbo) 
>>> print version 
1 
>>> 

यहाँ तक पहुँचने का एक और तरीका है, चर 'नाम' को दर्शाता है 'dbo [' m '] [' प '] [' वी '] [' संस्करण '] ', जो बहुत छोटा और साफ दिखता है।

यह विधि KeyError को फेंक नहीं देगी। यदि कोई कुंजी नहीं मिली है तो आपको 'कोई नहीं' मिलेगा।

रेफरी .: http://code.activestate.com/recipes/475156-using-reduce-to-access-deeply-nested-dictionaries/

+0

यदि आप नाम = 'm__foo__v__foo' का प्रयास करते हैं तो यह टाइपएरर फेंक देगा: टाइप एरर: डिस्क्रिप्टर 'get' को 'dict' ऑब्जेक्ट की आवश्यकता होती है लेकिन उसे 'noneType' प्राप्त होता है – krasnaya

संबंधित मुद्दे