当前位置: 首页 > 面试题库 >

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

邢飞鸿
2023-03-14
问题内容

我还没有找到解决方法。假设我收到这样的JSON对象:

{'1_data':{'4_data':[{'5_data':'hooray'}, {'3_data':'hooray2'}], '2_data':[]}}

很难立即说出,我该如何从 3_data键中 获取价值:data['1_data']['4_data'][1]['3_data']

我知道pprint,它有助于有点了解结构。但是有时数据量巨大,并且需要时间

有什么方法可以帮助我吗?


问题答案:

这是一组递归生成器,可用于搜索由字典和列表组成的对象。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_dictiter_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_list``iter_dict除了列表没有任何键,它只包含值之外,其工作方式与之类似。因此,我们不执行k == key测试,而是递归到原始列表包含的所有字典或列表。

该过程的最终结果是,当我们进行迭代时,find_key我们得到(索引,值)对,其中每个indices列表是dict键的序列和列表索引,这些索引成功地终止于带有所需键的dict项中,并且value是关联的值用那个特定的钥匙。

如果您想查看此代码的其他示例,请参阅如何修改嵌套Json的键以及如何从python的字典中选择深度嵌套的key:values。

还要看看我的新的,更简化的show_indices功能



 类似资料:
  • 问题内容: 有人可以解释函子是什么,并提供一个简单的例子吗? 问题答案: 函数对象就是这样。既是对象又是功能的东西。 另外:将函数对象称为“函子”是对术语的严重滥用:另一种“函子”是数学的中心概念,并且在计算机科学中具有直接作用(请参阅“ Haskell函子”)。该术语在ML中的使用也略有不同,因此,除非您正在Java中实现这些概念之一(可以!),否则请停止使用此术语。它使简单的事情变得复杂。 返

  • Object: JSON JSON解码器和编码器。 JSON Method: encode 转换一个对象或数组为JSON字符串。 语法: var myJSON = JSON.encode(obj); 参数: obj - (object) 转换为字符串的对象。 返回: (string) JSON字符串。 示例: var fruitsJSON = JSON.encode({apple: 'red',

  • 作为一个C新手,我真的很难理解C 11的新Move-Constructor,我希望有人可以解释我偶然发现的具体情况。让我们以此示例代码为例: 因此,我创建了一个 函数,该函数应将模型作为临时右值返回,并且我想将其分配给左值。我不希望编译器创建 对象的副本,因此我将复制构造函数定义为私有构造函数,并且我对赋值运算符执行相同的操作,以确保不复制任何数据。完成此操作后,代码不再正确编译,因此我添加了 M

  • 问题内容: 我具有以下实体结构:业务->广告活动->促销,其中一个业务可以有多个广告活动,一个业务可以具有多个促销。一对多关系都声明为LAZY。在我的代码中的一个地方,我需要从业务部门急切地获取两个集合,所以我这样做: 但是,查询返回的结果列表中包含4个业务对象,所有4个对象都引用同一个业务实例。在我的数据库中,该公司下有3个广告活动,而这3个广告活动下都有3个广告活动。 我有两个问题: 首先,我

  • 我很难理解以下函数的递归工作流程,以及它如何遍历排列排序数组。 让我感到困惑的一件特别的事情是“返回[nums[:]]”调用在递归函数中的行为。由于第9行再次调用自己,直到“start==2”,它什么时候继续执行第9行之后的行,以及它为哪个递归函数执行这些继续行? 抱歉,如果我的问题有点让人困惑,我最近才开始学习Python,希望更好地了解“return”调用在递归函数中的工作方式。任何建议都将不

  • 我目前正在做一个项目,我们必须从UML图制作代码。我了解UML类图的解剖结构,但我无法理解什么

  • 我遇到了这个问题,给定一个整数数组,判断整数序列是从左、右还是死端退出数组。您从左侧输入数组并沿指定方向移动N个索引(其中N是整数的值)(正是右,负是左) 我想到的一个解决方案是,若所有整数的值都是正的,那个么就向右退出或向左退出。但是,此解决方案并不涵盖所有场景。我需要帮助来解决这个问题。

  • 主要内容:1 Redis dict,1.1 扩缩容的条件,1.2 渐进式rehash操作,2 Redis ziplist,2.1 ziplist结构,2.2 entry结构,3 Redis quicklist详细介绍了Redis的底层数据结构:dict、ziplist、quicklist。 此前我们学习了常见的Reids数据类型,这些数据类型都需要底层的数据结构的支持,现在我们来看看Redis常见的底层数据结构:dict、ziplist、quicklist。 1 Redis dict dict就