Python中OrderedDict的使用
 

很多人认为python中的字典是无序的,因为它是按照hash来存储的,但是python中有个模块collections(英文,收集、集合),里面自带了一个子类OrderedDict,实现了对字典对象中元素的排序。

在Python 3.5(含)以前,字典是不能保证顺序的,键值对A先插入字典,键值对B后插入字典,但是当你打印字典的Keys列表时,你会发现B可能在A的前面。 但是从Python 3.6开始,字典是变成有顺序的了。你先插入键值对A,后插入键值对B,那么当你打印Keys列表的时候,你就会发现B在A的后面。 不仅如此,从Python 3.6开始,下面的三种遍历操作,效率要高于Python 3.5之前。

In [22]:
d = dict()
d['a'] = 'A'
d['m'] = 'm'
d['b'] = 'B'
d['1'] = 2
d['c'] = 'C'
d['d'] = 'D'
d['e'] = 'E'
d['2'] = 3
print(d)
 
{'a': 'A', 'm': 'm', 'b': 'B', '1': 2, 'c': 'C', 'd': 'D', 'e': 'E', '2': 3}
In [23]:
import collections

d1 = collections.OrderedDict()
d1['a'] = 'A'
d1['b'] = 'B'
d1['c'] = 'C'
d1['1'] = '1'
d1['2'] = '2'
print(d1)
 
OrderedDict([('a', 'A'), ('b', 'B'), ('c', 'C'), ('1', '1'), ('2', '2')])
 

可以看到,同样是保存了ABC等几个元素,但是使用OrderedDict会根据放入元素的先后顺序进行排序。所以输出的值是排好序的。

OrderedDict对象的字典对象,如果其顺序不同那么Python也会把他们当做是两个不同的对象,请看事例:

In [24]:
print('Regular dictionary:')
d2 = dict()
d2['a'] = 'A'
d2['b'] = 'B'
d2['c'] = 'C'

d3 = dict()
d3['c'] = 'C'
d3['a'] = 'A'
d3['b'] = 'B'
print(d2 == d3)

print('OrderedDict:')
d4 = collections.OrderedDict()
d4['a'] = 'A'
d4['b'] = 'B'
d4['c'] = 'C'

d5 = collections.OrderedDict()
d5['c'] = 'C'
d5['a'] = 'A'
d5['b'] = 'B'

print(d4 == d5)
 
Regular dictionary:
True
OrderedDict:
False
In [25]:
dd = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
# 按key排序
kd = collections.OrderedDict(sorted(dd.items(), key=lambda t: t[0]))
print(kd)
# 按照value排序
vd = collections.OrderedDict(sorted(dd.items(), key=lambda t: t[1]))
print(vd)
 
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
 

有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。由于内置的 dict 类获得了记住插入顺序的能力(在 Python 3.6之后保证了这种新行为),它们变得不那么重要了。

OrderedDict 与 dict 的 Key 会按照插入的顺序排列,不是 Key 本身排序

一些与 dict 的不同仍然存在:

常规的 dict 被设计为非常擅长映射操作。 跟踪插入顺序是次要的。

OrderedDict 旨在擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的。

算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。 这使其适用于跟踪最近的访问(例如在 LRU cache 中)。

对于 OrderedDict ,相等操作检查匹配顺序。

OrderedDict 类的 popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。

OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。

Python 3.8之前, dict 缺少 reversed() 方法。

class collections.OrderedDict([items]):返回一个 dict 子类的实例,它具有专门用于重新排列字典顺序的方法。