繁体   English   中英

如何重命名具有任意深度的字典的 Python 字典中的键

[英]How to rename keys in a python dictionary of dictionaries with arbitrary depth

我有一本字典,其中包含字典,而字典又可能包含无穷无尽的字典。 我想更改所有字典中的每个键,但映射到嵌套字典之一的键除外。 我知道密钥是不可变的,我想做这样的事情:

layer[item + '_addition'] = layer.pop(item)

我现在拥有的是:

def alterKeys(item, layer=topLevelDict):
    if isinstance(item, dict):
        for i in item:
            alterKeys(item[i], item)
    else:
        layer[item + '_addition'] = layer.pop(item)

这是行不通的,因为它会不断地沿着树向下递归,直到最后一行尝试从字典中弹出一个值,而不是一个键,这会引发 KeyError。 我知道我已经接近解决方案了,但是我已经考虑了几分钟,但似乎无法弄清楚。

在写这个问题时,我想通了。 我想我会发布这个以防其他人在某个时候有同样的问题。

def alterKeys(item, layer=topLevelDict, key=None):
    if isinstance(item, dict):
        for k, v in item.items():
            alterKeys(v, item, k)
    elif isinstance(key, str):
        layer[key + '_addition'] = layer.pop(key)

如果有人有更优雅或更好的解决方案,我很乐意看到它。 我刚刚通过运行一个 json 文件来测试这个脚本,它重命名了每个没有映射到字典的键,这正是我想要的。

如果我想重命名每个键,包括那些映射到嵌套字典的键,我可以使用以下代码:

def alterKeys(item, layer=topLevelDict, key=None):
    if isinstance(item, dict):
        for k, v in item.items():
            alterKeys(v, item, k)
    if isinstance(key, str):
        layer[key + '_addition'] = layer.pop(key)

如果您使用的是 python2,请记住使用 .iteritems() 而不是 .items(),并使用 isinstance(key, basestring) 而不是 isinstance(key, str)。

我在寻找这个问题的一个轻微变体的解决方案时遇到了这个问题,所以我想我会发布我自己的 python 3.7.4 解决方案。

以下代码将遍历一个对象,该对象是有序 dict 和 list 的嵌套组合,以下代码将所有名为@index字段重命名为id

from collections import OrderedDict

def rename_index_to_id(iterable):
    if type(iterable) is OrderedDict:
        for key in list(iterable.keys()):
            if key == "@index":
                iterable["id"] = iterable["@index"]
                del iterable[key]
        for obj in iterable:
            rename_index_to_id(iterable[obj])
    elif type(iterable) is list:
        for obj in iterable:
            rename_index_to_id(obj)

我修改了@ martin-riddar解决方案,使其更通用。

from collections import OrderedDict
def rename_dict_key(the_dict, old_key_name, new_key_name):
  if type(the_dict) in [dict, OrderedDict]:
    for key in list(the_dict.keys()):
      if key == old_key_name:
        the_dict[new_key_name] = the_dict[old_key_name]
        del the_dict[key]
    for obj in the_dict:
      rename_dict_key(the_dict[obj], old_key_name, new_key_name)
  elif type(the_dict) is list:
    for obj in the_dict:
      rename_dict_key(obj, old_key_name, new_key_name)

注意:我使用dict而不是OrderedDict对此进行了测试,尽管我不希望结果会有所不同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM