9

辞書を含む辞書があります。辞書には辞書も含まれる場合があります。

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

現在、ID 001 の「Bill To」、「Transaction Ref」a1 を次のように取得するために開梱しています。

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

これは少しぎこちなく、特に最後の 2 行だと思わずにはいられません。

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

中間変数に展開することなく、ネストされた辞書にドリルダウンするためのより簡単なアプローチはありますか?

4

3 に答える 3

20

You can use something like this:

>>> 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

Additionally, if you don't want to define your search keys as individual parameters, you can just pass them in as a list like this:

>>> print lookup(d, *['a', 'b', 'c'])
5
>>> print lookup(d, *['a', 'c'])
None
于 2012-07-28T13:43:05.447 に答える
15
bill_to = transactions['Transaction Details']['Bill To']

実際に動作します。transactions['Transaction Details']は a を表す式なdictので、その中でルックアップを行うことができます。ただし、実用的なプログラムの場合は、入れ子になった dict に対してオブジェクト指向アプローチを使用することをお勧めします。collections.namedtupleデータのみを含む (独自の動作を含まない) 一連のクラスをすばやくセットアップする場合に特に便利です。

注意点が 1 つあります。一部の設定では、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
于 2012-07-28T12:03:51.027 に答える
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
>>>

ここで、変数 'name' は 'dbo['m']['d']['v']['version']' を参照しており、これははるかに短くてきれいに見えます。

このメソッドは KeyError をスローしません。キーが見つからない場合は、'None' が返されます。

参照: http://code.activestate.com/recipes/475156-using-reduce-to-access-deeply-nested-dictionaries/

于 2014-12-16T11:51:53.003 に答える