如何重命名字典列表中深度嵌套的键(Python 3)?
Posted
技术标签:
【中文标题】如何重命名字典列表中深度嵌套的键(Python 3)?【英文标题】:How to rename a deeply nested key in list of dictionaries (Python 3)? 【发布时间】:2021-08-03 20:56:56 【问题描述】:给定以下字典(很长的字典列表的一部分):
'diet': 'Diet 0': 'gender': 0,
'nutrients': 'Alcohol': 'min': 0, 'max': 14, 'unit': 'oz',
'Caffeine': 'min': 0, 'max': 400, 'unit': 'mg',
'Copper': 'min': 0, 'max': 0, 'unit': 'mg',
'Calcium': 'min': 1000, 'max': 2500, 'unit': 'mg',
'Choline': 'min': 425, 'max': 3500, 'unit': 'mg',
'Cholesterol': 'min': 0, 'max': 300, 'unit': 'mg',
'Fluoride': 'min': 0, 'max': 0, 'unit': 'mg',
'SaturatedFat': 'min': 0, 'max': -1, 'unit': 'g',
'VitaminA': 'min': 2330, 'max': 10000, 'unit': 'IU',
'VitaminC': 'min': 75, 'max': 2000, 'unit': 'mg',
'VitaminD': 'min': 15, 'max': 100, 'unit': 'mcg',
'VitaminE': 'min': 15, 'max': 1000, 'unit': 'mg',
'VitaminK': 'min': 0, 'max': 0, 'unit': 'mcg',
'VitaminB1': 'min': 1.1, 'max': 0, 'unit': 'mg',
'VitaminB2': 'min': 0, 'max': 0, 'unit': 'mg',
'VitaminB5': 'min': 0, 'max': 0, 'unit': 'mg',
'VitaminB3': 'min': 0, 'max': 0, 'unit': 'mg',
'VitaminB6': 'min': 0, 'max': 0, 'unit': 'mg',
'VitaminB12': 'min': 2.4, 'max': 999999999, 'unit': 'mcg',
'Fiber': 'min': 21, 'max': 70, 'unit': 'g',
'Folate': 'min': 400, 'max': 1000, 'unit': 'mcg',
'FolicAcid': 'min': 0, 'max': 0, 'unit': 'mcg',
'Iodine': 'min': 0, 'max': 0, 'unit': 'mcg',
'Iron': 'min': 18.0, 'max': 45, 'unit': 'mg',
'Magnesium': 'min': 310, 'max': 350, 'unit': 'mg',
'Manganese': 'min': nan, 'max': 0, 'unit': 'mg',
'Phosphorus': 'min': 700, 'max': 4000, 'unit': 'mg',
'Potassium': 'min': 2600, 'max': 0, 'unit': 'mg',
'Selenium': 'min': 0, 'max': 0, 'unit': 'mcg',
'Sodium': 'min': 500, 'max': 2300, 'unit': 'mg',
'Sugar': 'min': nan, 'max': 24, 'unit': 'g',
'Zinc': 'min': 8.0, 'max': 40, 'unit': 'mg'
我的列表中有 10000 个这样的字典,我想将 SaturatedFat
键更改为 Saturated Fat
。
试过ast
:
import ast
ast.literal_eval(str(diet_specs_dicts[0]).replace("'SaturatedFat':","'Saturated Fat':"))
返回错误:
----------------------------------- ---------------------------- ValueError Traceback(最近一次调用 最后)在 1 导入 ast ----> 2 ast.literal_eval(str(diet_specs_dicts[0]).replace("'SaturatedFat':","'Saturated 胖子':"))
/usr/lib/python3.8/ast.py in literal_eval(node_or_string) 97 左右返回 98 返回_convert_signed_num(节点) ---> 99 返回 _convert(node_or_string) 100 101
/usr/lib/python3.8/ast.py 在 _convert(node) 86 如果 len(node.keys) != len(node.values): 87 _raise_malformed_node(节点) ---> 88 返回 dict(zip(map(_convert, node.keys), 89 地图(_convert,node.values))) 90 elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):
/usr/lib/python3.8/ast.py 在 _convert(node) 86 如果 len(node.keys) != len(node.values): 87 _raise_malformed_node(节点) ---> 88 返回 dict(zip(map(_convert, node.keys), 89 地图(_convert,node.values))) 90 elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):
/usr/lib/python3.8/ast.py 在 _convert(node) 86 如果 len(node.keys) != len(node.values): 87 _raise_malformed_node(节点) ---> 88 返回 dict(zip(map(_convert, node.keys), 89 地图(_convert,node.values))) 90 elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):
/usr/lib/python3.8/ast.py 在 _convert(node) 86 如果 len(node.keys) != len(node.values): 87 _raise_malformed_node(节点) ---> 88 返回 dict(zip(map(_convert, node.keys), 89 地图(_convert,node.values))) 90 elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):
/usr/lib/python3.8/ast.py 在 _convert(node) 86 如果 len(node.keys) != len(node.values): 87 _raise_malformed_node(节点) ---> 88 返回 dict(zip(map(_convert, node.keys), 89 地图(_convert,node.values))) 90 elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):
/usr/lib/python3.8/ast.py 在 _convert(node) 96 其他: 97 左右返回 ---> 98 返回 _convert_signed_num(node) 99 返回 _convert(node_or_string) 100
/usr/lib/python3.8/ast.py in _convert_signed_num(node) 其他 73 条: 74 返回 - 操作数 ---> 75 返回 _convert_num(node) 76 def _convert(节点): 77 if isinstance(node, Constant):
/usr/lib/python3.8/ast.py in _convert_num(node) 64 def_convert_num(节点): 65 if not isinstance(node, Constant) or type(node.value) not in (int, float, complex): ---> 66 _raise_malformed_node(节点) 67 返回节点值 68 def_convert_signed_num(节点):
/usr/lib/python3.8/ast.py 在 _raise_malformed_node(node) 61 node_or_string = node_or_string.body 62 def _raise_malformed_node(节点): ---> 63 raise ValueError(f'malformed node or string: node!r') 64 def_convert_num(节点): 65 if not isinstance(node, Constant) or type(node.value) not in (int, float, complex):
ValueError:错误的节点或字符串:<_ast.name object at>
【问题讨论】:
使用 json 可能会更好。您可以json.dumps
将字典转换为字符串,然后进行 str 替换,然后 json.loads
将其恢复为字典
你有没有尝试将'SaturatedFat'的值复制到'Saturated Fat',然后用my_dict.pop('key', None)
删除原来的key?
你有一个变量“nan”,值是多少?
@Yuri nan 已修复。它应该是 0。
@AimiHat 是的,没用。这是一个嵌套的字典。
【参考方案1】:
给你
lst = ['diet': 'Diet 0': 'gender': 0,
'nutrients': 'Alcohol': 'min': 0, 'max': 14, 'unit': 'oz',
'Caffeine': 'min': 0, 'max': 400, 'unit': 'mg',
'Copper': 'min': 0, 'max': 0, 'unit': 'mg',
'Calcium': 'min': 1000, 'max': 2500, 'unit': 'mg',
'Choline': 'min': 425, 'max': 3500, 'unit': 'mg',
'Cholesterol': 'min': 0, 'max': 300, 'unit': 'mg',
'Fluoride': 'min': 0, 'max': 0, 'unit': 'mg',
'SaturatedFat': 'min': 0, 'max': -1, 'unit': 'g',
'VitaminA': 'min': 2330, 'max': 10000, 'unit': 'IU',
'VitaminC': 'min': 75, 'max': 2000, 'unit': 'mg',
'VitaminD': 'min': 15, 'max': 100, 'unit': 'mcg',
'VitaminE': 'min': 15, 'max': 1000, 'unit': 'mg',
'VitaminK': 'min': 0, 'max': 0, 'unit': 'mcg',
'VitaminB1': 'min': 1.1, 'max': 0, 'unit': 'mg',
'VitaminB2': 'min': 0, 'max': 0, 'unit': 'mg',
'VitaminB5': 'min': 0, 'max': 0, 'unit': 'mg',
'VitaminB3': 'min': 0, 'max': 0, 'unit': 'mg', ............................]
for d in lst:
d['Saturated Fat'] = d.pop('SaturatedFat')
print(lst)
【讨论】:
很抱歉,它不起作用。它说没有这样的密钥:--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-16-80d329dbdb21> in <module> ----> 1 diet_specs_dicts[0].pop('SaturatedFat') KeyError: 'SaturatedFat'
你能发布完整的错误吗?我不确定你为什么提到diet_specs_dicts[0] ...你是否缩进只替换“0”索引??
在我的情况下,它是列表的名称,所以我采用第一个 (0) 元素并尝试更改键名。在您的情况下,列表的名称是 lst。
发布完整的错误,将给出解决方案。代码有效,可能需要小修改。
在这里,我将使用列表中的前 2 个字典:lst = [diet_specs_dicts[0], diet_specs_dicts[1]]
并运行您的解决方案:for d in lst: d['Saturated Fat'] = d.pop('SaturatedFat')
【参考方案2】:
您可以使用递归函数来更改键,无论它出现在嵌套层次结构中的什么地方:
针对函数定义中的拼写错误进行了编辑
>>> d = 'diet': 'Diet 0': 'gender': 0,
...: 'nutrients': 'Alcohol': 'min': 0, 'max': 14, 'unit': 'oz',
...: 'Caffeine': 'min': 0, 'max': 400, 'unit': 'mg',
...: 'SaturatedFat': 'min': 0, 'max': -1, 'unit': 'g',
...: 'VitaminA': 'min': 2330, 'max': 10000, 'unit': 'IU'
>>> def replace_key(d, old_key, new_key):
...: for k, v in tuple(d.items()):
...: if k == old_key:
...: d[new_key] = d.pop(old_key)
...:
...: if isinstance(v, dict):
...: replace_key(v, old_key, new_key)
...:
>>> replace_key(d, old_key='SaturatedFat', new_key='Saturated Fat')
>>> d
'diet': 'Diet 0': 'gender': 0,
'nutrients': 'Alcohol': 'min': 0, 'max': 14, 'unit': 'oz',
'Caffeine': 'min': 0, 'max': 400, 'unit': 'mg',
'VitaminA': 'min': 2330, 'max': 10000, 'unit': 'IU',
'Saturated Fat': 'min': 0, 'max': -1, 'unit': 'g'
这个函数就地改变字典,并返回None
,但很容易修改为返回副本,保持原字典不变:
>>> import copy
>>> def replace_key(d, old_key, new_key):
...: d = copy.deepcopy(d)
...: for k, v in tuple(d.items()):
...: if k == old_key:
...: d[new_key] = d.pop(old_key)
...:
...: if isinstance(v, dict):
...: replace_key(v, old_key, new_key)
...:
...: return d
【讨论】:
这里的 x 是什么:x(v, old_key, new_key)
对不起 - “x”是一个错字。应该是“replace_key”。我已经更新了答案以上是关于如何重命名字典列表中深度嵌套的键(Python 3)?的主要内容,如果未能解决你的问题,请参考以下文章