Crossin的编程教室

标题: 【每周一课】 有序字典 OrderedDict [打印本页]

作者: 江水滔滔    时间: 2017-2-23 10:24
标题: 【每周一课】 有序字典 OrderedDict

编程课堂将和每周一坑一样,成为本教室公众号的一个长期固定栏目。每期讲解一个编程知识点,包括但不限于 Python 语法、模块介绍、编程小技巧等。用简短的篇幅,让你多了解一点编程。

作者: 江水滔滔    时间: 2017-2-23 10:25
有序字典 OrderedDict
---------------------------------------------


在我们的 Python 入门系列文章中,有介绍过字典 dict:【Python 第37课】 字典。其中有简单提及到,字典中的键值对是没有顺序的,所以无法像列表或元组一样通过索引来访问元素。
这简单的一笔带过恐怕不能引起注意,那么来看这个例子:


d = {}
d['c'] = 3
d['b'] = 2
d['a'] = 1
print(d)


在你的电脑上运行下,看看输出结果是什么?
有的人会是:


{'a': 1, 'b': 2, 'c': 3}


有的人则是:


{'a': 1, 'c': 3, 'b': 2}


如果你改变一下字典赋值的顺序,结果可能没有变化,也可能发生了变化……
dict 的实现方式决定了其是无序的(hash 映射,这里不展开),添加键值对的先后顺序和最终输出显示的顺序没有任何关系。
这一点和 list 是不一样的,在 python shell 中这样试下便可明白:


>>> [1, 2] == [2, 1]
False
>>> {'a':1, 'b':2} == {'b':2, 'a':1}
True


这也导致一些同学在刚刚编写代码时感到困惑:
为什么字典的结果不按照我想要的顺序来?
好在 Python 里提供了一个解决方案:OrderedDict
在官方文档中,可以找到如下描述:
Ordered dictionaries are just like regular dictionaries but they remember the order that items were inserted. When iterating over an ordered dictionary, the items are returned in the order their keys were first added.
简单来说,就是有序字典和普通的字典并无差异,但是它记录了条目添加的顺序,当迭代有序字典时,字典内容随着被添加的顺序返回。
如果你在 python shell 中输入:


>>> from collections import OrderedDict
>>> help(OrderDict)


可以看到第一行写着:


class OrderedDict(__builtin__.dict)
也就是说,OrderedDict 是 dict 的子类。所以你可以放心地像 dict 一样来使用它。而同时,它又增加了对添加顺序的记录:


from collections import OrderedDict
d = OrderedDict()
d['c'] = 3
d['b'] = 2
d['a'] = 1
print(d)


无论在什么环境下,输出结果都是:


OrderedDict([('c', 3), ('b', 2), ('a', 1)])


如果用 for 循环遍历,一样会保持这个顺序:


for key in d:
print(key, d[key])


输出(py3):


c 3
b 2
a 1


如果现在你有一个字典,想要对其按照一定的规则进行排序,则可通过 sorted + OrderedDict 来实现:


from collections import OrderedDict
d = {'a': 2, 'b': 3, 'c': 1}
# 以 value 值对 dic 排序
sd = sorted(d.items(), key=lambda x: x[1])
# 转换为有序字典
od = OrderedDict(sd)
print(od)


如此就生成了一个排序后的有序字典。由于是 dict 的子类,所以字典的方法它都可以使用,这里不再赘述。提两个 OrderedDict 新增的方法:


popitem(last=True)


默认去除最后的条目,如果想删除第一条,将 True 改为 False


>>> od.popitem()
('b', 3)
>>> od
OrderedDict([('c', 1), ('a', 2)])


move_to_end(key, last=True)
(py3中新增)移动 key 对应的条目到顺序末端,last=False 时调整到首位


>>> od.move_to_end('a')
>>> od
OrderedDict([('c', 1), ('b', 3), ('a', 2)])


关于 OrderedDict 就介绍到这里。你可能已经注意到,OrderedDict 是 collections 模块中的一个类。
collections 是 Python 自带的一个非常好用的模块,在常见的 dict、list、set、tuple 等类型之上,提供了额外的容器数据类型。
之后我们还将会介绍其中的其他实用功能。等不及的同学可以自行搜索相关内容或查阅官方文档。





欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5