2013-05-10 3 views
221

Gibt es eine Möglichkeit, einen Wörterbuchschlüssel umzubenennen, ohne seinen Wert einem neuen Namen zuzuweisen und den alten Namensschlüssel zu entfernen; und ohne durch dict key/value zu iterieren?

Im Falle von OrderedDict, das gleiche tun, während die Position dieser Taste beibehalten wird.Umbenennen eines Wörterbuchschlüssels

+5

was genau bedeuten, verstehen Sie unter „ohne seinen Wert zu einem neuen Namen neu zuzuzuweisen und die alten Namen Schlüssel zu entfernen "? So wie ich das sehe, ist das die Definition der Umbenennung eines Schlüssels, und alle folgenden Antworten weisen den Wert zu und entfernen den alten Schlüsselnamen. Sie müssen noch eine Antwort akzeptieren, also haben diese vielleicht nicht das erreicht, wonach Sie suchen? – dbliss

Antwort

14

einen Scheck für newkey!=oldkey Verwendung, auf diese Weise können Sie tun:

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

Für eine regelmäßige dict, können Sie verwenden:

mydict[new_key] = mydict.pop(old_key) 

Für eine OrderedDict, ich glaube, Sie ein völlig bauen müssen neue mit einem Verständnis.

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

Ändern der Schlüssel selbst, wie diese Frage zu stellen, scheint zu sein, ist unpraktisch, weil dict Schlüssel sind in der Regel unveränderlich Objekte wie Zahlen, Strings oder Tupel. Anstatt zu versuchen, den Schlüssel zu ändern, indem Sie den Wert einem neuen Schlüssel zuweisen und den alten Schlüssel entfernen, können Sie das "Umbenennen" in Python erreichen.

+0

Für python 3.5 denke ich, dass 'dict.pop' basierend auf meinem Test für ein OrderedDict praktikabel ist. – Daniel

+1

Nein, 'OrderedDict' wird die Reihenfolge beibehalten, was nicht die Frage ist. – wim

+0

Sie haben Recht, mein Fehler. – Daniel

7

können Sie diese OrderedDict recipe von Raymond Hettinger geschrieben verwenden und ändern Sie es eine rename Methode hinzufügen, aber das wird ein O (N) in ihrer Komplexität sein:

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 

Beispiel:

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 

Ausgang:

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

Sieht nach einem sehr guten Ansatz aus, aber wie kann ich das zu meinem Skript hinzufügen? – MERose

+1

@MERose Fügen Sie die Python-Datei irgendwo in Ihrem Modul-Suchpfad hinzu und importieren Sie 'OrderedDict' daraus. Aber ich würde empfehlen: Erstellen Sie eine Klasse, die von 'OrderedDict' erbt und fügen Sie ihr eine' rename' Methode hinzu. –

37

beste Methode in 1 Zeile:

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

Was ist, wenn Sie 'd = {('test', 'foo') haben: [0,1,2]}'? –

+1

@PetrFedosov, dann tun Sie 'd [('neu', 'Schlüssel')] = d.pop (('test', 'foo'))' –

+1

Diese Antwort kam _zwei Jahre _ nach der Antwort von wim, die genau dasselbe vorschlägt Ding, ohne zusätzliche Informationen. Was vermisse ich? –

0

Ein paar Leute vor mir erwähnte den .pop Trick zu löschen und einen Schlüssel in einem Einzeiler zu erstellen.

Ich persönlich finde die explizite Implementierung besser lesbar:

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

Der obige Code gibt {'a': 1, 'c': 2}