it-swarm.com.de

Benennen Sie einen Wörterbuchschlüssel um

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 dikt Schlüssel/Wert iterieren?

Im Fall von OrderedDict machen Sie dasselbe, während Sie die Position dieses Schlüssels beibehalten.

319
rabin utam

Für ein normales Diktat können Sie Folgendes verwenden:

mydict[new_key] = mydict.pop(old_key)

Für ein OrderedDict müssen Sie meines Erachtens aus einem Verständnis ein völlig neues bauen.

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

Das Ändern des Schlüssels selbst, wie diese Frage zu stellen scheint, ist unpraktisch, da diktierte Schlüssel normalerweise nveränderlich Objekte wie Zahlen, Zeichenfolgen oder Tupel sind. Anstatt zu versuchen, den Schlüssel zu ändern, können Sie den Wert einem neuen Schlüssel zuweisen und den alten Schlüssel entfernen, um das "Umbenennen" in Python zu erreichen.

594
wim

beste Methode in 1 Zeile:

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

Mit einer Prüfung auf newkey!=oldkey können Sie folgendermaßen vorgehen:

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

Sie können dieses OrderedDict recipe verwenden, das von Raymond Hettinger geschrieben wurde, und es ändern, um eine rename -Methode hinzuzufügen, dies wird jedoch eine O(N) sein. in der Komplexität:

_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
_

Ausgabe:

_OrderedDict({'a': 1, 'b': 2, 'c': 3})
foo 1
bar 2
c 3
spam 5
_
10

Einige Leute vor mir erwähnten den Trick .pop, um einen Schlüssel in einem Einzeiler zu löschen und zu erstellen.

Ich persönlich finde die explizitere Implementierung lesbarer:

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

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

3
Uri Goren

Andere Antworten sind ziemlich gut. Aber in python3.6 hat reguläres Dikt auch Ordnung. Daher ist es im Normalfall schwierig, die Position des Schlüssels beizubehalten.

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
2
helloswift123

Im Falle des Umbenennens aller Wörterbuchschlüssel:

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)
1

In Python 3.6 (weiter?) Würde ich den folgenden Einzeiler wählen

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()))

was produziert

{'a': 1, 'new': 4, 'c': 3}

Es kann erwähnenswert sein, dass ohne die Anweisung print die ipython console/jupyter notebook das Wörterbuch in einer Reihenfolge ihrer Wahl anzeigt ...

1
KeithWM

Auch wenn es sich um eine Diktatliste handelt, konvertieren Sie sie einfach in einen String.

NOTE: Stellen Sie sicher, dass Sie nicht den gleichen Wertnamen wie den Schlüsselnamen haben.

Könnte für jemanden arbeiten

import json
d = [{'a':1,'b':2},{'a':2,'b':3}]
d = json.loads(json.dumps(d).replace('"a"','"newKey"'))
0
deusxmachine

@ helloswift123 Ich mag deine Funktion. Hier ist eine Änderung, um mehrere Tasten in einem einzigen Anruf umzubenennen:

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
0
skullgoblet1089

Angenommen, Sie möchten den Schlüssel k3 in k4 umbenennen:

temp_dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
temp_dict['k4']= temp_dict('k3')
0
shishir bondre

Für den Fall, dass jemand alle Schlüssel auf einmal umbenennen möchte und eine Liste mit den neuen Namen erstellt:

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()}
0
Sirmione

Ich verwende die obige Antwort von @wim mit dict.pop (), wenn ich Schlüssel umbenenne, aber ich habe ein gotcha gefunden. Das Durchlaufen des Diktats, um die Schlüssel zu ändern, ohne die Liste der alten Schlüssel vollständig von der Diktatinstanz zu trennen, führte dazu, dass neue, geänderte Schlüssel in der Schleife durchlaufen wurden und einige vorhandene Schlüssel fehlten.

Zunächst habe ich es so gemacht:

for current_key in my_dict:
    new_key = current_key.replace(':','_')
    fixed_metadata[new_key] = fixed_metadata.pop(current_key)

Ich stellte fest, dass das Wörterbuch beim Durchlaufen des Diktats immer wieder nach Schlüsseln suchte, auch wenn dies nicht der Fall sein sollte, d. H. Nach den neuen Schlüsseln, die ich geändert hatte! Ich musste die Instanzen vollständig voneinander trennen, um (a) meine eigenen geänderten Schlüssel nicht in der for-Schleife zu finden und (b) einige Schlüssel zu finden, die aus irgendeinem Grund nicht in der Schleife gefunden wurden.

Ich mache das jetzt:

current_keys = list(my_dict.keys())
for current_key in current_keys:
    and so on...

Das Konvertieren der my_dict.keys () in eine Liste war erforderlich, um den Verweis auf das sich ändernde Diktat zu entfernen. Durch die Verwendung von my_dict.keys () wurde ich an die ursprüngliche Instanz gebunden, mit den seltsamen Nebenwirkungen.

0
excyberlabber