重命名字典键

问题描述 投票:301回答:12

有没有办法重命名字典键,而无需将其值重新分配给新名称并删除旧名称键;并且没有迭代通过dict键/值? 在OrderedDict的情况下,执行相同的操作,同时保持该键的位置。

python dictionary associative-array ordereddictionary
12个回答
585
投票

对于常规字典,您可以使用:

mydict[new_key] = mydict.pop(old_key)

对于OrderedDict,我认为你必须使用理解来构建一个全新的。

>>> 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中实现“重命名”。


0
投票

如果有人想要一次重命名所有密钥,提供一个包含新名称的列表:

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()}

0
投票

假设您要将密钥k3重命名为k4:

temp_dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
temp_dict['k4']= temp_dict('k3')

0
投票

如果重命名所有字典键:

dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
new_keys = ['k4','k5','k6']

for key,n_key in zip(dict,new_keys):
    dict[n_key] = dict.pop(key)

53
投票

1行最佳方法:

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

26
投票

使用newkey!=oldkey检查,您可以这样做:

if newkey!=oldkey:  
    dictionary[newkey] = dictionary[oldkey]
    del dictionary[oldkey]

10
投票

您可以使用由Raymond Hettinger编写的这个OrderedDict recipe并修改它以添加rename方法,但这将是O(N)的复杂性:

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

例:

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

输出:

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

3
投票

在我之前的一些人提到了.pop技巧删除并在单行中创建一个键。

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

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

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


2
投票

其他答案都很不错。但是在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

1
投票

在Python 3.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()))

哪个产生

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

值得注意的是,如果没有print语句,ipython console / jupyter笔记本会按照他们选择的顺序显示字典...


0
投票

即使它的dict列表只是将其转换为字符串。

注意:确保您没有与键名相同的值名称。

可能会为某人工作

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

0
投票

我正在使用@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()让我绑定到原始实例,具有奇怪的副作用。

© www.soinside.com 2019 - 2024. All rights reserved.