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)
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)
这里有一系列递归生成器,可用于搜索由dict和list组成的对象。
find_key
生成一个元组,其中包含字典键的列表和指向您传入的键的列表索引;该元组还包含与该键关联的值。因为它是一个生成器,如果对象包含多个匹配键(如果需要的话),它将找到所有匹配的键。在输出
^{pr2}$要获得一个单键列表,可以将
find_key
传递给next
函数。如果您想使用一个键列表来获取相关的值,您可以使用一个简单的for
循环。在输出
如果键可能丢失,那么给
next
一个适当的默认元组。例如:输出
注意,这段代码是为python3编写的。要在python2上运行它,您需要替换所有
yield from
语句,例如replace与
工作原理
要理解这段代码是如何工作的,您需要熟悉recursion和Python generators。您可能还会发现这个页面很有帮助:Understanding Generators in Python;在线上还有各种Python生成器教程。在
json.load
或json.loads
返回的Python对象通常是dict,但也可以是列表。我们将该对象作为obj
参数和我们要定位的key
字符串一起传递给find_key
生成器。find_key
然后根据需要调用iter_dict
或{indices
,该列表用于收集dict键并列出指向所需键的索引。在iter_dict
在其d
dict arg的顶层迭代每个(k,v)对。如果k
与我们要查找的键匹配,则生成当前的indices
列表,并附加k
以及相关联的值。因为iter_dict
是递归的,所以产生的(索引列表,值)对被传递到上一级递归,最终到达find_key
,然后传递到调用find_key
的代码。请注意,这是递归的“基本情况”:它是代码的一部分,决定这个递归路径是否指向我们想要的键。如果递归路径从未找到与我们要查找的键匹配的键,那么该递归路径不会向indices
添加任何内容,它将终止而不会产生任何结果。在如果当前的
v
是dict,那么我们需要检查它包含的所有(key,value)对。我们通过递归调用iter_dict
,传递v
是它的起始对象和当前的indices
列表。如果当前的v
是一个列表,我们改为将其称为iter_list
,并传递相同的参数。在iter_list
的工作原理与iter_dict
相似,除了列表没有任何键,它只包含值,所以我们不执行k == key
测试,我们只递归到原始列表中包含的任何dict或list。在这个过程的最终结果是,当我们迭代
find_key
时,我们会得到一对(索引,值),其中每个indices
列表是dict键的序列和成功地用我们所需的键终止在dict项中的索引,value
是与该特定键关联的值。在如果您想看看这段代码的其他使用示例,请参见how to modify the key of a nested Json和How can I select deeply nested key:values from dictionary in python。在
同时看看我的新的、更精简的^{} 函数。在
相关问题 更多 >
编程相关推荐