2013-05-10 22 views
221

C'è un modo per rinominare una chiave di dizionario, senza riassegnare il suo valore a un nuovo nome e rimuovere la vecchia chiave di nome; e senza iterare attraverso chiave/valore di dict?

In caso di OrderedDict, fare lo stesso, mantenendo la posizione di quella chiave.Rinomina una chiave di dizionario

+5

cosa esattamente cosa si intende per "senza riassegnando il suo valore a un nuovo nome e rimuovendo la chiave vecchio nome "? il modo in cui lo vedo, è la definizione di rinominare una chiave, e tutte le risposte sottostanti riassegnano il valore e rimuovono il vecchio nome della chiave. devi ancora accettare una risposta, quindi forse questi non hanno raggiunto quello che stai cercando? – dbliss

risposta

14

Utilizzando un assegno di newkey!=oldkey, in questo modo si può fare:

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

Per un dict regolare, è possibile utilizzare:

mydict[new_key] = mydict.pop(old_key) 

Per un OrderedDict, penso che si deve costruire uno completamente nuovo usando una comprensione.

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

Modifica della chiave stessa, in quanto questa domanda sembra chiedersi, è impraticabile perché le chiavi dict sono di solito immutabili oggetti come numeri, stringhe o tuple. Invece di provare a modificare la chiave, riassegnare il valore a una nuova chiave e rimuovere la vecchia chiave è come ottenere la "rinomina" in python.

+0

Per python 3.5, penso che 'dict.pop' sia lavorabile per un OrderedDict basato sul mio test. – Daniel

+1

No, 'OrderedDict' manterrà l'ordine di inserimento, che non è quello che la domanda ha posto. – wim

+0

Hai ragione, mio ​​errore. – Daniel

7

È possibile utilizzare questo OrderedDict recipe scritto da Raymond Hettinger e modificarlo per aggiungere un metodo rename, ma questo sta per essere un O (N) in complessità:

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 

Esempio:

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 

uscita:

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

Sembra un approccio molto buono, ma come posso aggiungerlo al mio script? – MERose

+1

@MERose Aggiungi il file Python da qualche parte nel tuo percorso di ricerca del modulo e importa 'OrderedDict' da esso. Ma raccomanderei: creare una classe che erediti da "OrderedDict" e aggiungere un metodo "rename" ad esso. –

37

metodo migliore in 1 linea:

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

cosa succede se hai 'd = {('test', 'pippo'): [0,1,2]}'? –

+1

@PetrFedosov, quindi fai 'd [('nuovo', 'chiave')] = d.pop (('test', 'foo'))' –

+1

Questa risposta è arrivata _due anni_ dopo la risposta di wim che suggerisce lo stesso identico cosa, senza ulteriori informazioni. Cosa mi manca? –

0

Alcune persone prima di me menzionato il trucco .pop eliminare e creare una chiave in un one-liner.

Personalmente trovo l'attuazione più esplicito più leggibile:

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

Il codice restituisce sopra {'a': 1, 'c': 2}

Problemi correlati