有没有一种方法可以重命名字典键,而无需将其值重新分配给新名称并删除旧名称键;而不迭代字典键/值?
对于OrderedDict,在保持键的位置的同时执行相同的操作。
OrderedDict
。字典在进行相等性比较时会忽略顺序,而OrderedDict
在进行比较时会考虑顺序。我知道您链接到了可以解释它的内容,但我认为您的评论可能误导了那些可能未阅读该链接的人。
有没有一种方法可以重命名字典键,而无需将其值重新分配给新名称并删除旧名称键;而不迭代字典键/值?
对于OrderedDict,在保持键的位置的同时执行相同的操作。
OrderedDict
。字典在进行相等性比较时会忽略顺序,而OrderedDict
在进行比较时会考虑顺序。我知道您链接到了可以解释它的内容,但我认为您的评论可能误导了那些可能未阅读该链接的人。
Answers:
对于常规命令,可以使用:
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中实现“重命名”,而不是尝试修改键,而是将值重新分配给新键并删除旧键。
dict.pop
根据我的测试,我认为适用于OrderedDict。
OrderedDict
将保留插入顺序,这不是问题所要解决的。
1行中的最佳方法:
>>> d = {'test':[0,1,2]}
>>> d['test2'] = d.pop('test')
>>> d
{'test2': [0, 1, 2]}
d = {('test', 'foo'):[0,1,2]}
办?
d[('new', 'key')] = d.pop(('test', 'foo'))
通过使用check newkey!=oldkey
,可以这样:
if newkey!=oldkey:
dictionary[newkey] = dictionary[oldkey]
del dictionary[oldkey]
dict
顺序,即使python3.6 +以有序形式将其初始化,以前的版本也没有,并且它并不是一个真正的功能,只是py3.6 +字典更改方式的后遗症。OrderedDict
如果您关心订单,请使用。
如果重命名所有字典键:
target_dict = {'k1':'v1', 'k2':'v2', 'k3':'v3'}
new_keys = ['k4','k5','k6']
for key,n_key in zip(target_dict.keys(), new_keys):
target_dict[n_key] = target_dict.pop(key)
target_dict.keys()
保证与定义中的顺序相同?我认为Python字典是无序的,并且字典键视图的顺序是无法预测的
您可以使用OrderedDict recipe
Raymond Hettinger编写的代码并对其进行修改以添加一个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
OrderedDict
从中导入。但我建议:创建一个继承自该类的类,OrderedDict
并rename
为其添加一个方法。
在我之前的一些人提到了.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
我想出了这个功能,它不会使原始字典发生变异。该功能也支持字典列表。
import functools
from typing import Union, Dict, List
def rename_dict_keys(
data: Union[Dict, List[Dict]], old_key: str, new_key: str
):
"""
This function renames dictionary keys
:param data:
:param old_key:
:param new_key:
:return: Union[Dict, List[Dict]]
"""
if isinstance(data, dict):
res = {k: v for k, v in data.items() if k != old_key}
try:
res[new_key] = data[old_key]
except KeyError:
raise KeyError(
"cannot rename key as old key '%s' is not present in data"
% old_key
)
return res
elif isinstance(data, list):
return list(
map(
functools.partial(
rename_dict_keys, old_key=old_key, new_key=new_key
),
data,
)
)
raise ValueError("expected type List[Dict] or Dict got '%s' for data" % type(data))
重命名密钥时,我在dict.pop()中使用了@wim的答案,但是我发现了一个问题。在dict上循环以更改键,而又未将旧键列表与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()转换为列表对于释放对更改的dict的引用是必要的。仅使用my_dict.keys()就使我与原始实例保持联系,并产生了奇怪的副作用。
如果有人想一次重命名所有键,并提供一个包含新名称的列表:
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()}
@ helloswift123我喜欢您的功能。这是在单个调用中重命名多个键的修改:
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