2013-05-10 17 views
221

Czy istnieje sposób zmiany nazwy klucza słownika, bez ponownego przypisywania jego wartości do nowej nazwy i usuwania starego klucza nazwy; i bez iteracji poprzez klucz/wartość dyktowania?
W przypadku OrderedDict, zrób to samo, zachowując pozycję tego klucza.Zmień nazwę klucza słownika

+5

co dokładnie masz na myśli przez „bez realokacja jej wartość na nową nazwą i usunięcie starej nazwy klucza "? tak jak ja to widzę, to jest definicja zmiany nazwy klucza, a wszystkie odpowiedzi poniżej ponownie przypisać wartość i usunąć starą nazwę klucza. nie zaakceptowałeś jeszcze odpowiedzi, więc może ci nie osiągnęli tego, czego szukasz? – dbliss

Odpowiedz

14

Korzystanie czek na newkey!=oldkey, w ten sposób można zrobić:

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

Dla zwykłego dict, można użyć:

mydict[new_key] = mydict.pop(old_key) 

Dla OrderedDict, myślę, że trzeba zbudować zupełnie nowy za pomocą zrozumienia.

>>> 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')]) 

Modyfikowanie samego klucza, jak ta kwestia wydaje się pytać, jest niepraktyczne, ponieważ klucze dict są zwykle niezmienne obiekty, takie jak numery, ciągi lub krotek. Zamiast próbować modyfikować klucz, ponowne przypisanie wartości do nowego klucza i usunięcie starego klucza jest sposobem uzyskania "zmiany nazwy" w pythonie.

+0

Dla Pythona 3.5, myślę, że 'dict.pop' jest wykonalny dla OrderedDict na podstawie mojego testu. – Daniel

+1

Nie, 'OrderedDict' zachowa kolejność wstawiania, co nie jest tym, o co pytano. – wim

+0

Masz rację, mój błąd. – Daniel

7

Można użyć tej OrderedDict recipe napisany przez Raymond Hettinger i zmodyfikować go dodać metodę rename, ale to będzie O (N) złożoności:

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 

Przykład:

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 

wyjściowa:

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

Wygląda na bardzo dobre podejście, ale jak mogę dodać to do mojego skryptu? – MERose

+1

@MERose Dodaj plik Pythona gdzieś w ścieżce wyszukiwania modułu i zaimportuj z niego 'OrderedDict'. Ale polecam: Utwórz klasę dziedziczącą po 'OrderedDict' i dodaj do niej metodę' rename'. –

37

najlepsza metoda w 1 linii:

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

co jeśli masz 'd = {('test', 'foo'): [0,1,2]}'? –

+1

@PetrFedosov, następnie robisz 'd [('new', 'key')] = d.pop (('test', 'foo'))' –

+1

Ta odpowiedź nadeszła dwa lata po odpowiedzi Wima, która sugeruje dokładnie to samo rzecz bez dodatkowych informacji. czego mi brakuje? –

0

Kilka osób przede mną wspomniał o .pop sztuczki, aby usunąć i utworzyć klucz w jednej liniowej.

Ja osobiście znaleźć bardziej wyraźny wdrożenie bardziej czytelny:

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

Powyższy kod zwraca {'a': 1, 'c': 2}