如何动态处理嵌套字典中price字段的字典/字典列表转换
处理嵌套字典中动态类型的price字段转换问题
问题场景
遍历从JSON转换而来的嵌套字典时,price字段的值存在两种类型:有时是单个字典,有时是字典列表。示例数据如下:
Data={"main": {"sub_main": [ {"id": "995", "item": "850", "price": {"ref": "razorback", "value": "250"}}, {"id": "953", "item": "763", "price": [{"ref": "razorback", "value": "450"},{"ref": "sumatra", "value": "370"},{"ref": "ligea", "value": "320"} ]}, ]}}
根据id过滤后,转换为字典时会因price类型不同报错:
- 当
price是字典时,常规推导式可正常生成字典:result1 = [item["price"] for item in Data["main"]["sub_main"] if item["id"]=="995"] dresult={k:v for e in result1 for (k,v) in e.items()} - 当
price是字典列表时,相同代码会抛出'list' object has no attribute 'items'错误:result2 = [item["price"] for item in Data["main"]["sub_main"] if item["id"]=="953"] # 执行此代码会报错 dresult={k:v for e in result2 for (k,v) in e.items()}
解决方案
核心思路是统一归一化处理:先将所有price字段转为字典列表格式,再通过推导式生成最终字典。这种方法支持动态类型检测,可高效处理数千条数据。
方法1:分步处理(清晰直观)
先对过滤后的结果做类型归一化,再生成字典:
# 先根据id过滤得到结果(以id=953为例) result = [item["price"] for item in Data["main"]["sub_main"] if item["id"]=="953"] # 归一化:将单个字典转为包含该字典的列表,列表则直接展开 normalized_prices = [] for entry in result: if isinstance(entry, dict): normalized_prices.append(entry) elif isinstance(entry, list): normalized_prices.extend(entry) # 生成最终字典(ref作为键,value作为值,重复ref会被后续值覆盖) dresult = {item["ref"]: item["value"] for item in normalized_prices}
方法2:合并流程(高效简洁)
将过滤、归一化、字典生成合并为一步,减少中间变量,更适合大数据量处理:
target_id = "995" # 可替换为任意目标id normalized_prices = [] for item in Data["main"]["sub_main"]: if item["id"] == target_id: price = item["price"] # 动态判断类型并添加到列表 if isinstance(price, dict): normalized_prices.append(price) elif isinstance(price, list): normalized_prices.extend(price) # 生成最终字典 dresult = {entry["ref"]: entry["value"] for entry in normalized_prices}
方法3:一行式推导(极简写法)
用嵌套列表推导式完成归一化,再生成字典:
target_id = "953" # 先过滤并归一化price字段 normalized_prices = [ entry for item in Data["main"]["sub_main"] if item["id"] == target_id for entry in (item["price"] if isinstance(item["price"], list) else [item["price"]]) ] dresult = {entry["ref"]: entry["value"] for entry in normalized_prices}
说明
- 最终生成的
dresult为标准字典类型,可直接用于Django视图展示。 - 如果存在多个
price项有相同ref值,后面的value会覆盖前面的,若需保留所有值可将字典值改为列表(如{entry["ref"]: dresult.get(entry["ref"], []) + [entry["value"]] for entry in normalized_prices})。
内容的提问来源于stack exchange,提问作者Zembla
相关产品推荐
相关产品推荐

