Переименуйте ключ словаря

Есть ли способ переименовать ключ словаря, не переназначая его значение для нового имени и удаляя старый ключ имени; и без итерации через ключ/значение 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')