その値を新しい名前に再割り当てして古い名前のキーを削除せずに、辞書のキーの名前を変更する方法はありますか。そしてdictキー/値を繰り返すことなく?
OrderedDictの場合は、そのキーの位置を保ちながら、同じ操作を行います。
通常の辞書には、次のものを使用できます。
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')])
この質問が尋ねているように、キー自体を変更することは実用的ではありません。Dictキーは通常数字、文字列、タプルなどの不変なオブジェクトだからです。キーを変更しようとする代わりに、新しいキーに値を再割り当てして古いキーを削除するのではなく、pythonで "名前の変更"を行うことができます。
1行で最良の方法:
>>> d = {'test':[0,1,2]}
>>> d['test2'] = d.pop('test')
>>> d
{'test2': [0, 1, 2]}
newkey!=oldkey
のチェックを使用して、このようにすることができます:
if newkey!=oldkey:
dictionary[newkey] = dictionary[oldkey]
del dictionary[oldkey]
Raymond Hettingerによって書かれたこれ OrderedDict recipe
を使用してrename
メソッドを追加することができますが、これは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
私の前に数人の人々がワンライナーでキーを削除して作成するための.pop
トリックを述べました。
私は個人的には、より明示的な実装の方が読みやすいと思います。
d = {'a': 1, 'b': 2}
v = d['b']
del d['b']
d['c'] = v
上記のコードは{'a': 1, 'c': 2}
を返します
他の答えはかなり良いです。python3.6で、通常の辞書も注文しています。そのため、通常の場合、キーの位置を維持するのは困難です。
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
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ノートブックは辞書を選んだ順に表示します。
すべての辞書キーの名前を変更する場合
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)
たとえその辞書のリストが単にそれを文字列に変換したとしても。
NOTE:キー名と同じ名前の値がないことを確認してください。
誰かのために働くかもしれない
import json
d = [{'a':1,'b':2},{'a':2,'b':3}]
d = json.loads(json.dumps(d).replace('"a"','"newKey"'))
@ helloswift123私はあなたの機能が好きです。 1回の呼び出しで複数のキーの名前を変更するための変更を次に示します。
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
キーk3をk4に名前変更したいとします。
temp_dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
temp_dict['k4']= temp_dict('k3')
誰かが一度にすべてのキーの名前を変更したい場合は、新しい名前のリストを用意してください。
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()}
キーの名前を変更するときに、dict.pop()で@wimの答えを使用していますが、問題点が見つかりました。 dictインスタンスから古いキーのリストを完全に切り離すことなく、キーを変更するためにキーを変更するためにキーを変更すると、新しい変更されたキーをループに入れ替え、既存のキーをいくつか失います。
まず始めに、私はこのようにしました:
for current_key in my_dict:
new_key = current_key.replace(':','_')
fixed_metadata[new_key] = fixed_metadata.pop(current_key)
私はこのようにして辞書をたどっていくと、たとえそれがあってはならない場合でも辞書がキーを見つけ続けること、すなわち新しいキー、私が変更したものを見つけたことを私は発見した。 (a)forループ内で自分で変更されたキーを見つけるのを避け、(b)何らかの理由でループ内で見つからなかったキーを見つけるために、インスタンスを互いに完全に分離する必要がありました。
私は今これをやっています:
current_keys = list(my_dict.keys())
for current_key in current_keys:
and so on...
My_dict.keys()をリストに変換することは、変化する辞書への参照を解放するために必要でした。 my_dict.keys()を使用するだけで、奇妙な副作用を伴い、元のインスタンスに結び付けられました。