是否有一种方法重命名字典键,而不重新分配其值为一个新名称和删除旧的名称键;并且没有通过dict键/值迭代?

在OrderedDict的情况下,做同样的事情,同时保持该键的位置。


当前回答

我使用@wim的答案上面,dict.pop()重命名键时,但我发现了一个问题。循环遍历dict以更改键,而没有将旧键列表与dict实例完全分离,结果将新的、已更改的键循环到循环中,并丢失一些现有的键。

首先,我是这样做的:

for current_key in my_dict:
    new_key = current_key.replace(':','_')
    fixed_metadata[new_key] = fixed_metadata.pop(current_key)

我发现,以这种方式循环字典,字典一直在找到键,即使它不应该,也就是说,新的键,我已经改变的那些!我需要将实例彼此完全分开,以(a)避免在for循环中找到我自己更改的键,以及(b)找到由于某种原因在循环中没有找到的一些键。

我现在正在做这件事:

current_keys = list(my_dict.keys())
for current_key in current_keys:
    and so on...

必须将my_dict.keys()转换为列表,以摆脱对不断变化的dict的引用。仅使用my_dict.keys()将我与原始实例绑定在一起,并产生奇怪的副作用。

其他回答

我使用@wim的答案上面,dict.pop()重命名键时,但我发现了一个问题。循环遍历dict以更改键,而没有将旧键列表与dict实例完全分离,结果将新的、已更改的键循环到循环中,并丢失一些现有的键。

首先,我是这样做的:

for current_key in my_dict:
    new_key = current_key.replace(':','_')
    fixed_metadata[new_key] = fixed_metadata.pop(current_key)

我发现,以这种方式循环字典,字典一直在找到键,即使它不应该,也就是说,新的键,我已经改变的那些!我需要将实例彼此完全分开,以(a)避免在for循环中找到我自己更改的键,以及(b)找到由于某种原因在循环中没有找到的一些键。

我现在正在做这件事:

current_keys = list(my_dict.keys())
for current_key in current_keys:
    and so on...

必须将my_dict.keys()转换为列表,以摆脱对不断变化的dict的引用。仅使用my_dict.keys()将我与原始实例绑定在一起,并产生奇怪的副作用。

我结合了上面帖子中的一些答案,并提出了下面的解决方案。虽然它很简单,但它可以用作从字典中进行更复杂的键更新的构建块。

test_dict = {'a': 1, 'b': 2, 'c': 3}
print(test_dict)
# {'a': 1, 'b': 2, 'c': 3}
prefix = 'up'
def dict_key_update(json_file):    
    new_keys = []
    old_keys = []
    for i,(key,value) in enumerate(json_file.items()):
        old_keys.append(key)
        new_keys.append(str(prefix) + key) # i have updated by adding a prefix to the 
        # key
    for old_key, new_key in zip(old_keys,new_keys):
        print('old {}, new {}'.format(old_key, new_key))
        if new_key!=old_key:  
           json_file[new_key] = json_file.pop(old_key)
     return json_file

test_dict = dict_key_update(test_dict)
print(test_dict)
# {'upa': 1, 'upb': 2, 'upc': 3}

其他答案也很不错。但在python3.6中,常规字典也有顺序。所以在正常情况下很难保持键的位置。

def rename(old_dict,old_name,new_name):
    new_dict = {}
    for key,value in zip(old_dict.keys(),old_dict.values()):
        new_key = key if key != old_name else new_name
        new_dict[new_key] = old_dict[key]
    return new_dict

我想出了这个函数,它不会改变原来的字典。这个函数也支持字典列表。

import functools
from typing import Union, Dict, List


def rename_dict_keys(
    data: Union[Dict, List[Dict]], old_key: str, new_key: str
):
    """
    This function renames dictionary keys

    :param data:
    :param old_key:
    :param new_key:
    :return: Union[Dict, List[Dict]]
    """
    if isinstance(data, dict):
        res = {k: v for k, v in data.items() if k != old_key}
        try:
            res[new_key] = data[old_key]
        except KeyError:
            raise KeyError(
                "cannot rename key as old key '%s' is not present in data"
                % old_key
            )
        return res
    elif isinstance(data, list):
        return list(
            map(
                functools.partial(
                    rename_dict_keys, old_key=old_key, new_key=new_key
                ),
                data,
            )
        )
    raise ValueError("expected type List[Dict] or Dict got '%s' for data" % type(data))

在我之前的一些人提到了.pop技巧,可以在一行程序中删除和创建一个键。

我个人认为更显式的实现更具可读性:

d = {'a': 1, 'b': 2}
v = d['b']
del d['b']
d['c'] = v

上面的代码返回{'a': 1, 'c': 2}