【编程课堂】有序字典 OrderedDict

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

上周每周一坑的题目 三门问题 将在本周讲解,还没有看过的同学赶紧的。

在我们的 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的编程教室(crossincode)

原文发表时间:2017-02-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏锦小年的博客

python学习笔记7.4-内建模块base64

有时候,我们用noepad++或者记事本打开图片或者程序等文件的时候会显示大量的乱码,主要原因是这些文件编码的时候并不是字符串编码的。如果我们想把这些文件正常显...

2129
来自专栏企鹅号快讯

编程语言学啥?当然首选Python啦!千字长文教你如何入门Python!

1.1 流程控制之for循环 ? 1.2 开发工具IDE 1.2.1 为何要用IDE ? 很多语言都有比较流行的开发工具,比如JAVA 的Eclipse, C#...

4166
来自专栏JavaEdge

设计模式实战-迭代器模式

迭代器是为容器服务的,那什么是容器呢? 能容纳对象的所有类型都可以称之为容器,例如Collection集合类型、Set类型等,迭代器模式就是为解决遍历这些容器中...

2092
来自专栏大史住在大前端

野生前端的数据结构基础练习(2)——队列

循环队列书中并没有提及,它是一种特殊的队列。简单理解就是将基本队列只当做存储结构,而使用front和rear两个指针分别代表队列的头和尾,实际对外表现的队列是f...

2023
来自专栏余林丰

Effective Java通俗理解(下)

第31条:用实例域代替序数   枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用...

2489
来自专栏向治洪

python 日期与时间

###python 日期与时间 (time,datetime包) [toc] #####概述 在应用程序的开发过程中,难免要跟日期、时间处理打交道。如:记录一个...

30310
来自专栏Java后端技术栈

关于Java代码优化的N条建议!

本文是作者:五月的仓颉 结合自己的工作和平时学习的体验重新谈一下为什么要进行代码优化。在修改之前,作者的说法是这样的:

1132
来自专栏前端达人

JavaScript基础——Promise使用指南

在上篇文章里《JavaScript基础——回调(callback)是什么》我们一起学习了回调,明白了回调就是一个在另外一个函数执行完后要执行的函数,如果我们希望...

2753
来自专栏java一日一条

10个惊艳的Swift单行代码

几年前,一篇表述“10个Scala函数式单行代码”的文章非常受欢迎,并且随后立马出现了其他的语言版本,例如Haskell版本,Ruby版本,Groovy版本,C...

852
来自专栏walterlv - 吕毅的博客

.NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)

发布于 2018-09-02 14:27 更新于 2018-09...

4911

扫码关注云+社区