Есть ли способ переименовать ключ словаря, не переназначая его значение для нового имени и удаляя старый ключ имени; и без итерации через ключ/значение dict?
В случае OrderedDict, сделайте то же самое, сохраняя эту позицию ключа.
Переименуйте ключ словаря
Ответ 1
Для обычного dict вы можете использовать:
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')])
Изменение самого ключа, как кажется, задается этим вопросом, нецелесообразно, поскольку ключи ключа - это обычно неизменные объекты, такие как числа, строки или кортежи. Вместо того, чтобы пытаться изменить ключ, переназначение значения на новый ключ и удаление старого ключа - это то, как вы можете добиться "переименования" в python.
Ответ 2
лучший метод в 1 строке:
>>> d = {'test':[0,1,2]}
>>> d['test2'] = d.pop('test')
>>> d
{'test2': [0, 1, 2]}
Ответ 3
Используя проверку для newkey!=oldkey
, выполните следующие действия:
if newkey!=oldkey:
dictionary[newkey] = dictionary[oldkey]
del dictionary[oldkey]
Ответ 4
Вы можете использовать этот OrderedDict recipe
, написанный Раймондом Хеттингером, и изменить его, чтобы добавить метод rename
, но это будет a 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
Ответ 5
В случае переименования всех ключей словаря:
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)
Ответ 6
Несколько человек до меня упомянули трюк .pop
чтобы удалить и создать ключ в одну .pop
.
Лично я нахожу более явную реализацию более читабельной:
d = {'a': 1, 'b': 2}
v = d['b']
del d['b']
d['c'] = v
Код выше возвращает {'a': 1, 'c': 2}
Ответ 7
Другие ответы довольно хороши. Но в python3.6 регулярный dict также имеет порядок. Поэтому сложно удерживать ключевую позицию в обычном случае.
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
Ответ 8
Даже если это список dict, просто конвертируйте его в строку.
ПРИМЕЧАНИЕ. Убедитесь, что у вас нет значений, совпадающих с именем ключа.
Может работать на кого-то
import json
d = [{'a':1,'b':2},{'a':2,'b':3}]
d = json.loads(json.dumps(d).replace('"a"','"newKey"'))
Ответ 9
В 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 представляет словарь в порядке их выбора...
Ответ 10
Я использую ответ @wim выше, с dict.pop() при переименовании ключей, но я нашел ошибку. Циклическое переключение по диктату для изменения ключей без полного ветки списка старых ключей от экземпляра dict приводило к циклическому изменению новых, измененных ключей в цикле и отсутствию некоторых существующих ключей.
Для начала я сделал это так:
for current_key in my_dict:
new_key = current_key.replace(':','_')
fixed_metadata[new_key] = fixed_metadata.pop(current_key)
Я обнаружил, что, перебирая диктовку таким образом, словарь продолжал находить ключи, даже когда он не должен был, то есть новые ключи, те, которые я изменил! Мне нужно было полностью отделить экземпляры друг от друга, чтобы (а) избежать нахождения собственных измененных ключей в цикле for и (б) найти некоторые ключи, которые по какой-то причине не были найдены в цикле.
Я делаю это сейчас:
current_keys = list(my_dict.keys())
for current_key in current_keys:
and so on...
Преобразование my_dict.keys() в список было необходимо, чтобы освободить ссылку на изменяющийся диктат. Простое использование my_dict.keys() позволило мне быть привязанным к оригинальному экземпляру со странными побочными эффектами.
Ответ 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()}
Ответ 12
@helloswift123 Мне нравится твоя функция. Вот модификация для переименования нескольких ключей за один вызов:
def rename(d, keymap):
"""
:param d: old dict
:type d: dict
:param keymap: [{:keys from-keys :values to-keys} keymap]
:returns: new dict
:rtype: dict
"""
new_dict = {}
for key, value in zip(d.keys(), d.values()):
new_key = keymap.get(key, key)
new_dict[new_key] = d[key]
return new_dict
Ответ 13
Предположим, вы хотите переименовать ключ k3 в k4:
temp_dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
temp_dict['k4']= temp_dict('k3')