亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

幫助理解json(dict)結構的函數

幫助理解json(dict)結構的函數

呼啦一陣風 2019-12-05 15:49:25
我還沒有找到解決方法。假設我收到這樣的JSON對象:{'1_data':{'4_data':[{'5_data':'hooray'}, {'3_data':'hooray2'}], '2_data':[]}}很難立即說出,我該如何從3_data鍵中獲取價值:data['1_data']['4_data'][1]['3_data']我知道pprint,它有助于有點了解結構。但是有時數據量巨大,并且需要時間有什么方法可以幫助我嗎?
查看完整描述

1 回答

?
郎朗坤

TA貢獻1921條經驗 獲得超9個贊

這是一組遞歸生成器,可用于搜索由字典和列表組成的對象。find_key產生一個元組,其中包含字典鍵列表和導致您傳入的鍵的列表索引;元組還包含與該鍵關聯的值。因為它是一個生成器,所以如果需要的話,如果對象包含多個匹配鍵,它將找到所有匹配鍵。


def find_key(obj, key):

    if isinstance(obj, dict):

        yield from iter_dict(obj, key, [])

    elif isinstance(obj, list):

        yield from iter_list(obj, key, [])


def iter_dict(d, key, indices):

    for k, v in d.items():

        if k == key:

            yield indices + [k], v

        if isinstance(v, dict):

            yield from iter_dict(v, key, indices + [k])

        elif isinstance(v, list):

            yield from iter_list(v, key, indices + [k])


def iter_list(seq, key, indices):

    for k, v in enumerate(seq):

        if isinstance(v, dict):

            yield from iter_dict(v, key, indices + [k])

        elif isinstance(v, list):

            yield from iter_list(v, key, indices + [k])


# test


data = {

    '1_data': {

        '4_data': [

            {'5_data': 'hooray'},

            {'3_data': 'hooray2'}

        ], 

        '2_data': []

    }

}


for t in find_key(data, '3_data'):

    print(t)

輸出


(['1_data', '4_data', 1, '3_data'], 'hooray2')

要獲取單個鍵列表,可以傳遞find_key給該next函數。如果要使用鍵列表來獲取關聯的值,則可以使用簡單的for循環。


seq, val = next(find_key(data, '3_data'))

print('seq:', seq, 'val:', val)


obj = data

for k in seq:

    obj = obj[k]

print('obj:', obj, obj == val)

輸出


seq: ['1_data', '4_data', 1, '3_data'] val: hooray2

obj: hooray2 True

如果密鑰可能丟失,請提供next適當的默認元組。例如:


seq, val = next(find_key(data, '6_data'), ([], None))

print('seq:', seq, 'val:', val)

if seq:

    obj = data

    for k in seq:

        obj = obj[k]

    print('obj:', obj, obj == val)

輸出


seq: [] val: None

請注意,此代碼是針對Python 3的。要在Python 2上運行,您需要替換所有yield from語句,例如replace


yield from iter_dict(obj, key, [])


for u in iter_dict(obj, key, []):

    yield u

怎么運行的

要了解此代碼的工作原理,您需要熟悉遞歸和Python 生成器。您可能還會發現此頁面有幫助:了解Python中的生成器;在線上也有各種Python生成器教程。


json.load或返回的Python對象json.loads通常是字典,但也可以是列表。我們將該對象find_key與objarg一起傳遞給生成器,作為key我們想要定位的字符串。find_key然后根據需要調用iter_dict或iter_list,將它們,對象,鍵和一個空列表傳遞給它們,該空列表indices用于收集dict鍵和列出指向所需鍵的索引。


iter_dict在其ddict arg 的頂層迭代每個(k,v)對。如果k與我們要查找的鍵匹配,則會生成當前indices列表k并附加到當前列表以及相關的值。因為iter_dict是遞歸的,所以產生的(索引列表,值)對將傳遞到遞歸的上一個級別,最終使它們到達find_key并到達調用的代碼find_key。請注意,這是遞歸的“基本情況”:這是確定此遞歸路徑是否指向所需鍵的代碼的一部分。如果遞歸路徑找不到與我們要查找的鍵匹配的鍵,則該遞歸路徑將不會添加任何內容,indices并且它將終止而不會產生任何結果。


如果當前v是一個字典,那么我們需要檢查它包含的所有(鍵,值)對。我們通過對進行遞歸調用來實現iter_dict,將v其作為起始對象和當前indices列表進行傳遞。如果當前v是一個列表,我們改為調用iter_list,將相同的參數傳遞給它。


iter_listiter_dict除了列表不包含任何鍵,它只包含值外,其工作方式與之類似。因此,我們不執行k == key測試,而是遞歸到原始列表包含的所有字典或列表。


該過程的最終結果是,當我們進行迭代時,find_key我們獲得(索引,值)對,其中每個indices列表是dict鍵的序列和列表索引,這些鍵成功地終止于帶有所需鍵的dict項中,并且value是關聯的值用那個特定的鑰匙。


如果您想查看此代碼的其他示例,請參閱如何修改嵌套Json的鍵以及如何從python的字典中選擇深度嵌套的key:values。


還要看看我的新的,更簡化的show_indices功能。


分享編輯


查看完整回答
反對 回復 2019-12-05
  • 1 回答
  • 0 關注
  • 328 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號