有时候面对一些需要处理的数据, 会是一种字典中嵌套字典的数据, 然后里面可能有多个key相同的value都是需要获取的, 比如json中的部分值.
这种直接获取比较困难, 只能自己写一个函数解决
1. 单纯字典的嵌套
下面的大概思路是迭代当前dict的所有元素, 对元素挨个依次比较key与所需要的key, 如果相同就保存在输出的list中.
然后如果遇到value是属于又一个dict, 则进行一个回归, 再次对这个子dict进行相同操作. 最后循环结束后输出list
然后还有可能有些我们搜索的key对应的value的类型有很多, 比如有可能是str的‘abc’, 也有可能是int的123, 也有可能是dict的{‘1’: 123}还有可能是list的[1, 2, 3], tuple的(1, 2, 3). 所以可以设计一个参数来判断是否获取类型为list, dict, tuple的目标值.
# in_dict:需要处理的字典, target_key:目标键
# value:输出的列表,元素为目标键值对应的值(必须为空列表), not_ldt:获取的目标类型不为dict
dicts = {'1': 1, '2': 2, '3': 3, '4': {'5': 55, '6': 66, '7': 77}, '7': {'7': 777}}
def get_dict_value(in_dict, target_key, results=[], not_d=True):
for key in in_dict.keys(): # 迭代当前的字典层级
data = in_dict[key] # 将当前字典层级的第一个元素的值赋值给data
# 如果当前data属于dict类型, 进行回归
if isinstance(data, dict):
get_dict_value(data, target_key, results=results, not_d=not_d)
# 如果当前键与目标键相等, 并且判断是否要筛选
if key == target_key and isinstance(data, dict) != not_d:
results.append(in_dict[key])
return results
上面的函数可以实现单纯的对嵌套字典的回归查找.
比如:
- 默认:
# 获取dicts中所有key为‘7’的value, 并且默认的不获取类型为dict的value.
a = get_dict_value(dicts, '7', results=[])
print(a)
输出:
[77, 777]
- 修改not_ldt参数:
# 获取dicts中所有key为‘7’的value, 并且获取类型为dict的value.
a = get_dict_value(dicts, '7', results=[], not_d=False)
print(a)
输出:
[77, 777, {'7': 777}]
- 注意⚠️: 有个问题就是, 如果要对函数调用两次, 因为value值在第一次调用的时候没有清空, 所以第二次调用的时候会出现第一次的结果. 解决办法就是每次调用的时候添加
value=[]
参数清空value值.
# 当调用连续两次函数的时候, 不对results进行初始化的时候:
a = get_dict_value(dicts, '7')
b = get_dict_value(dicts, '7')
print(b)
输出:
[77, 777, 77, 777]
可见每次调用的时候最好使用value=[]
初始化一下. 这个问题暂时没有想出好方法解决, 如果有更好的方法, 欢迎大家评论指出咯.
2. 字典,列表,元组的多类型嵌套
上面那个默认的字典里面元素的值要么是字符, 数字, 或者就是字典类型的, 所以在if判断的时候只有一个判断是否为dict类型的, 但是实际上, 对于要处理json数据的时候, 里面的字典的元素可能是list, tuple之类的, 比如:{‘1’: 1, 2: [{‘33’: 33}, (44, 55, 66)]}这种类型的内部元素比较复杂的json.
下面对上面的函数进行更新, 以期望实现更加具有通用性的功能, 毕竟遇见复杂的类型的json数据的情况更加多一点.
# in_json:需要处理的json数据, target_key:目标键
# value:输出的列表,元素为目标键值对应的值(必须为空列表)
dd = {'a': 'ok1', '1': {'1': 11, '2': ('a', 111, {'a': 'ok2'}, [{'a': 'ok3'}, 2222], {'a': [11111, 22222]})}, '2': '2'} # json数据例子
def get_json_value_by_key(in_json, target_key, results=[]):
if isinstance(in_json, dict): # 如果输入数据的格式为dict
for key in in_json.keys(): # 循环获取key
data = in_json[key]
get_json_value_by_key(data, target_key, results=results) # 回归当前key对于的value
if key == target_key: # 如果当前key与目标key相同就将当前key的value添加到输出列表
results.append(data)
elif isinstance(in_json, list) or isinstance(in_json, tuple): # 如果输入数据格式为list或者tuple
for data in in_json: # 循环当前列表
get_json_value_by_key(data, target_key, results=results) # 回归列表的当前的元素
return results
上面的函数便可以实现, 更加复杂的嵌套有列表, 元组的字典的查找.
比如:
- 默认:
# 当调用连续两次函数的时候, 不对results进行初始化的时候:
= get_dict_value(dd, 'a')
print(a)
输出:
['ok1', 'ok2', 'ok3', [11111, 22222]]
这个函数依然存在连续多次调用时, 需要初始化的不然会包含前面的结果的问题.