如何递归修改字典中指定键的所有值(含标量与列表元素)
解决方案:递归遍历字典并处理指定键的标量/列表值
以下是一个符合需求的Python函数,能够递归遍历嵌套字典,对指定键对应的标量值或列表元素应用自定义函数,同时跳过值为字典的目标键(避免非可处理类型报错):
def apply_to_keys(data, target_keys, func): if isinstance(data, dict): processed = {} for key, value in data.items(): # 先递归处理嵌套结构,确保深层目标键被优先处理 processed_value = apply_to_keys(value, target_keys, func) if key in target_keys: # 仅对列表或非字典的标量值应用函数 if isinstance(processed_value, list): processed[key] = [func(item) for item in processed_value] elif not isinstance(processed_value, dict): processed[key] = func(processed_value) else: # 值为字典时,直接保留递归处理后的结果 processed[key] = processed_value else: processed[key] = processed_value return processed elif isinstance(data, list): # 递归处理列表中的每个元素 return [apply_to_keys(item, target_keys, func) for item in data] else: # 标量值直接返回,等待上层判断是否应用函数 return data
函数逻辑说明
- 递归遍历:遇到字典时逐个处理键值对,遇到列表时逐个处理元素,确保所有嵌套层级都被覆盖;
- 目标键处理:仅当键在指定列表中,且对应值为列表或非字典标量时,才应用自定义函数:
- 列表:遍历每个元素并应用函数;
- 标量:直接应用函数;
- 字典:跳过函数应用,仅保留递归处理后的嵌套结构;
- 非目标键:直接保留递归处理后的结果,不做额外修改。
示例验证
使用你提供的测试数据和需求验证:
输入数据
original_data = { "name": ["joe", "bob", "jane"], "rank": "beginner", "address": { "street": {"direction": "east", "name": "main"}, "town": {"name": "boston", "state": "mass"}, "name": {"first": "joe", "last": "smith"}, }, "clubs": { "art": {"name": "art club", "rank": "expert", "site": "art.com"}, }, "fake": { "real": {"name": "fake"}, "fake": {"name": "fake"}, }, }
调用函数
# 应用字符串大写函数,处理["name", "rank"]键 result = apply_to_keys(original_data, ["name", "rank"], str.upper)
输出结果
{ "name": ["JOE", "BOB", "JANE"], "rank": "BEGINNER", "address": { "street": {"direction": "east", "name": "MAIN"}, "town": {"name": "BOSTON", "state": "mass"}, "name": {"first": "joe", "last": "smith"} }, "clubs": {"art": {"name": "ART CLUB", "rank": "EXPERT", "site": "art.com"}}, "fake": {"real": {"name": "FAKE"}, "fake": {"name": "FAKE"}} }
注:你提供的预期输出中address下的town和name键缺失,推测是笔误。上述结果符合核心需求:所有层级的name和rank键,只要对应值是列表或标量,都已被转为大写;值为字典的address.name键则保留原有结构。
内容的提问来源于stack exchange,提问作者Mark Miller
相关产品推荐
相关产品推荐

