关于python:重命名字典键

Rename a dictionary key

有没有一种方法可以重命名字典键,而无需将其值重新分配给新名称并删除旧名称键;也无需重复使用dict键/值?在订购信息技术的情况下,也要这样做,同时保持钥匙的位置。


对于常规听写,您可以使用:

1
mydict[new_key] = mydict.pop(old_key)

对于一个有序的信息技术,我认为你必须用理解来构建一个全新的信息技术。

1
2
3
4
5
>>> OrderedDict(zip('123', 'abc'))
OrderedDict([('1', 'a'), ('2', 'b'), ('3', 'c')])
>>> oldkey, newkey = '2', 'potato'
>>> OrderedDict((newkey if k == oldkey else k, v) for k, v in _.viewitems())
OrderedDict([('1', 'a'), ('potato', 'b'), ('3', 'c')])

正如这个问题所要求的那样,修改键本身是不切实际的,因为dict键通常是不可变的对象,如数字、字符串或元组。不要试图修改键,而是将值重新分配给新键并删除旧键,这是在Python中实现"重命名"的方法。


一行中的最佳方法:

1
2
3
4
>>> d = {'test':[0,1,2]}
>>> d['test2'] = d.pop('test')
>>> d
{'test2': [0, 1, 2]}


使用EDOCX1[0]的支票,您可以这样做:

1
2
3
if newkey!=oldkey:  
    dictionary[newkey] = dictionary[oldkey]
    del dictionary[oldkey]


您可以使用这个由Raymond Hettinger编写的OrderedDict recipe,并将其修改为添加rename方法,但这将是一个复杂度为o(n):

1
2
3
4
5
def rename(self,key,new_key):
    ind = self._keys.index(key)  #get the index of old key, O(N) operation
    self._keys[ind] = new_key    #replace old key with new key in self._keys
    self[new_key] = self[key]    #add the new key, this is added at the end of self._keys
    self._keys.pop(-1)           #pop the last item in self._keys

例子:

1
2
3
4
5
6
7
8
dic = OrderedDict((("a",1),("b",2),("c",3)))
print dic
dic.rename("a","foo")
dic.rename("b","bar")
dic["d"] = 5
dic.rename("d","spam")
for k,v in  dic.items():
    print k,v

输出:

1
2
3
4
5
OrderedDict({'a': 1, 'b': 2, 'c': 3})
foo 1
bar 2
c 3
spam 5


在我之前的一些人提到了.pop技巧,即在一行程序中删除和创建密钥。

我个人认为更明确的实现更具可读性:

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

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


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

1
2
3
4
5
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


在python 3.6中(以后的版本?)我想买下面的一条

1
2
3
4
5
6
test = {'a': 1, 'old': 2, 'c': 3}
old_k = 'old'
new_k = 'new'
new_v = 4  # optional

print(dict((new_k, new_v) if k == old_k else (k, v) for k, v in test.items()))

哪个产生

1
{'a': 1, 'new': 4, 'c': 3}

可能值得注意的是,如果没有print声明,ipython控制台/jupyter笔记本会按照他们选择的顺序呈现字典……


如果有人想一次重命名所有键,请提供一个新名称列表:

1
2
3
4
5
6
7
8
9
10
11
def rename_keys(dict_, new_keys):
   """
     new_keys: type List(), must match length of dict_
   """


    # dict_ = {oldK: value}
    # d1={oldK:newK,} maps old keys to the new ones:  
    d1 = dict( zip( list(dict_.keys()), new_keys) )

          # d1{oldK} == new_key
    return {d1[oldK]: value for oldK, value in dict_.items()}

我在上面使用@wim的答案,在重命名密钥时使用dict.pop(),但我发现了一个gotcha。在dict中循环以更改键,而不将旧键列表与dict实例完全分离,从而导致循环新键、将键更改为循环,并且缺少一些现有键。

首先,我是这样做的:

10

我发现,通过这种方式循环通过听写,字典一直在寻找钥匙,即使它不应该,即,新的钥匙,我已经改变的那些!我需要将实例完全分开,以(a)避免在for循环中找到自己更改的键,(b)找到一些由于某种原因在循环中找不到的键。

我现在要做的是:

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

将my_dict.keys()转换为列表是摆脱对更改的dict的引用所必需的。仅使用my_dict.keys()就可以将我与原始实例绑定在一起,产生奇怪的副作用。


即使它是一个dict列表,也只需将其转换为字符串。

注意:确保值名称与键名称不同。

可能为某人工作

1
2
3
import json
d = [{'a':1,'b':2},{'a':2,'b':3}]
d = json.loads(json.dumps(d).replace('"a"','"newKey"'))