字典虽然现在保持插入顺序,但不能随意排序。如果您真的想使用字典顺序信息来构建树,我认为唯一可靠的方法是为每个交换操作构建一个新字典,复制原始字典的内容。
如果您想要一个任意排序的字典,更合理的方法是从 collections.abc.MutableMapping 继承并使用字典和其他一些数据结构(例如列表)跟踪该对象内的数据。
这听起来可能很复杂,但它可能比你想象的要简单:
from collections.abc import MutableMapping
class SuperOrdered(MutableMapping):
def __init__(self):
self.data = {}
self.order = []
def __setitem__(self, key, value):
if key not in self.data:
self.order.append(key)
self.data[key] = value
def __getitem__(self, key):
return self.data[key]
def __delitem__(self, key):
del self.data[key]
self.order.remove(key)
def __len__(self):
return len(self.data)
def __iter__(self):
yield from iter(self.order)
def replace_key(self, oldkey, newkey, value):
if newkey in self.data:
del self[newkey]
position = self.order.index(oldkey)
self.order[position] = newkey
self.data[newkey] = value
def __repr__(self):
return f"{self.__class__.__name__}({{{', '.join(repr(key) + ':' + repr(self.data[key]) for key in self)}}})"
瞧——映射+“replace_key”方法应该足以让您按照您的想法构建树。
这是上面交互式提示中的类:
In [18]: aa = SuperOrdered()
In [19]: aa["a"] = 1;aa["b"] = 2;aa["c"] = 3
In [20]: aa
Out[20]: SuperOrdered({'a':1, 'b':2, 'c':3})
In [21]: aa.replace_key("a", "d", 4)
In [22]: aa
Out[22]: SuperOrdered({'d':4, 'b':2, 'c':3})
除了这个答案,而且超出主题:如果你想检查一个我希望“生产就绪”的树实现,我已经发布了一个作为我的extradict 包的一部分(pip 可安装)。
更新:也可以从collections.OrderedDict 继承并在那里添加replace_key 方法。该代码必须处理 OrderedDict 内部,但这并不难。
外部链接:
Github modification