Python 在嵌套的json/dict中搜索与指定键匹配的多个键值
我有一个Python对象,它有多层dict和列表,其中包含我需要从中获取值的键。我发现了一个使用递归生成器的方法,它允许我提取一个键的值,但不能提取多个键的值。代码如下:Python 在嵌套的json/dict中搜索与指定键匹配的多个键值,python,json,dictionary,nested,Python,Json,Dictionary,Nested,我有一个Python对象,它有多层dict和列表,其中包含我需要从中获取值的键。我发现了一个使用递归生成器的方法,它允许我提取一个键的值,但不能提取多个键的值。代码如下: with open('data.json') as f: json_data = json.load(f) def find_key(obj, key): if isinstance(obj, dict): yield from iter_dict(obj, key, []) elif
with open('data.json') as f:
json_data = json.load(f)
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])
for c in find_key(json_data, 'customer_count'):
print(c)
结果:
(['calendar', 'weeks', 0, 'days', 1, 'availabilities', 0, 'customer_count'], 14)
(['calendar', 'weeks', 0, 'days', 2, 'availabilities', 0, 'customer_count'], 7)
另一个示例可以提取多个键,但不会在整个对象中递归:
[...]
keys = ("customer_count", "utc_start_at", "non_resource_bookable_capacity")
for k in keys:
keypath, val = next(find_key(json_data, k))
print("{!r}: {!r}".format(k, val))
结果:
'customer_count': 14
'utc_start_at': '2018-09-29T16:45:00+0000'
'non_resource_bookable_capacity': 18
如何遍历整个对象并提取上面显示的三个关键点
我期望的结果如下所示:
'customer_count': 14
'utc_start_at': '2018-09-29T16:45:00+0000'
'non_resource_bookable_capacity': 18
'customer_count': 7
'utc_start_at': '2018-09-29T16:45:00+0000'
'non_resource_bookable_capacity': 25
下面的示例函数将搜索一个dict(包括所有嵌套dict),以查找与要查找的键列表匹配的键/值对。该函数递归地循环遍历dict和它包含的任何嵌套dict,并列出它所包含的所有可能dict的列表,以检查匹配键
def find_key_value_pairs(q, keys, dicts=None):
if not dicts:
dicts = [q]
q = [q]
data = q.pop(0)
if isinstance(data, dict):
data = data.values()
for d in data:
dtype = type(d)
if dtype is dict or dtype is list:
q.append(d)
if dtype is dict:
dicts.append(d)
if q:
return find_key_value_pairs(q, keys, dicts)
return [(k, v) for d in dicts for k, v in d.items() if k in keys]
下面的示例使用json.load
将类似于json的示例数据集转换为dict,然后再将其传递给函数
import json
json_data = """
{"results_count": 2, "results": [{"utc_start_at": "2018-09-29T16:45:00+0000", "counts": {"customer_count": "14", "other_count": "41"}, "capacity": {"non-resource": {"non_resource_bookable_capacity": "18", "other_non_resource_capacity": "1"}, "resource_capacity": "10"}}, {"utc_start_at": "2018-10-29T15:15:00+0000", "counts": {"customer_count": "7", "other_count": "41"}, "capacity": {"non-resource": {"non_resource_bookable_capacity": "25", "other_non_resource_capacity": "1"}, "resource_capacity": "10"}}]}
"""
data = json.loads(json_data) # json_data is a placeholder for your json
keys = ['results_count', 'customer_count', 'utc_start_at', 'non_resource_bookable_capacity']
results = find_key_value_pairs(data, keys)
for k, v in results:
print(f'{k}: {v}')
# results_count: 2
# utc_start_at: 2018-09-29T16:45:00+0000
# utc_start_at: 2018-10-29T15:15:00+0000
# customer_count: 14
# customer_count: 7
# non_resource_bookable_capacity: 18
# non_resource_bookable_capacity: 25
那么你想要的结果是什么?你能编辑并显示你的最终结果是什么样子的吗?我最近注意到这个函数可能会重复,它会随机化新列表(结果)中元素的顺序。您能想到发生这种情况的任何原因,或者如何确保元素的顺序一致吗?更新了@TomAudre-可能是因为原始函数向后遍历了传递给
search\u queue
的列表(只是因为我没有花太多心思来维护此函数的顺序)。也就是说,我编辑了答案,通过列表队列转发,我认为应该可以为您获得所需的订单(但我不是100%确定)。感谢您的更新。我觉得我的环境有些奇怪。在OSX(Python3.7)上,元素的顺序是一致的。在我的Debian8服务器(Python3.4.2)上,我仍然得到随机顺序。再次感谢您再看一眼。@TomAudre这是因为在Python3.6之前,dicts是无序的。