当前位置:  开发笔记 > 编程语言 > 正文

有助于理解json(dict)结构的函数

如何解决《有助于理解json(dict)结构的函数》经验,为你挑选了1个好方法。

我还没有找到有办法做到这一点.假设我收到一个像这样的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> PM 2Ring..:

以下是一系列递归生成器,可用于搜索由dicts和列表组成的对象.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通常是一个dict,但它也可以是一个列表.我们将该对象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是dict,那么我们需要检查它包含的所有(键,值)对.我们通过递归调用来做到这一点iter_dict,传递它v是它的起始对象和当前indices列表.如果当前v是一个列表,我们反而调用iter_list,传递相同的args.

iter_list类似的工作iter_dict除了列表没有任何键,它只包含值,所以我们不执行k == key测试,我们只是递归到原始列表包含的任何dicts或列表.

这个过程的最终结果是,当我们迭代时,find_key我们得到成对的(索引,值),其中每个indices列表是dict键的序列和列表索引,它们使用我们想要的键成功终止在dict项中,并且value是相关的值用那个特定的钥匙.

如果你想看到这个代码的其他一些例子正在使用中,请看看如何修改嵌套Json的密钥以及如何从python中的字典中选择深层嵌套的key:values.

另外,请看看我新的,更简化的show_indices功能.

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有