Python的OrderedDict

0 前言

python中的字典常用来存储键值对数据,但是由于python中的dict类型底层实现是hash表,所以dict存储的数据是无序的,就是元素的输出顺序并不是我们添加到字典中的顺序。OrderedDict继承自dict,位于collections包,是有顺序的字典,它可以维护添加key-value对的顺序,底层的实现是哈希表加双链表,即可以实现元素的快速访问,又可以维护元素的顺序

1 OrderedDict

首先需要明确的是OrderedDict继承自dict,dict具有的特性和操作,OrderedDict都是具有的,关于dict的介绍请参考博客:python内置类型字典
由于 OrderedDict 能维护 key-value 对的添加顺序,因此即使两个 OrderedDict 中的 key-value 对完全相同,但只要它们的顺序不同,程序在判断它们是否相等时也依然会返回 false。

from collections import OrderedDict
# 创建OrderedDict对象,像创建字典一样具有多种创建的方式
dx = OrderedDict(b=5, c=2, a=7)
print(dx) # OrderedDict([('b', 5), ('c', 2), ('a', 7)])
d = OrderedDict()
# 向OrderedDict中添加key-value对
d['Python'] = 89
d['Swift'] = 92
d['Kotlin'] = 97
d['Go'] = 87
# 遍历OrderedDict的key-value对
for k,v in d.items():
    print(k, v)

上面程序首先创建了 OrderedDict 对象,接下来程序向其中添加了 4 个 key-value 对,OrderedDict 完全可以“记住”它们的添加顺序。运行该程序,可以看到如下输出结果:

OrderedDict([('b', 5), ('c', 2), ('a', 7)])
Python 89
Swift 92
Kotlin 97
Go 87

正如前面所说的,两个 OrderedDict 中即使包含的 key-value 对完全相同,但只要它们的顺序不同,程序也依然会判断出两个 OrderedDict 是不相等的。例如如下程序:

# 创建普通的dict对象
my_data = {'Python': 20, 'Swift':32, 'Kotlin': 43, 'Go': 25}
# 创建基于key排序的OrderedDict
d1 = OrderedDict(sorted(my_data.items(), key=lambda t: t[0]))
# 创建基于value排序的OrderedDict
d2 = OrderedDict(sorted(my_data.items(), key=lambda t: t[1]))
print(d1) # OrderedDict([('Go', 25), ('Kotlin', 43), ('Python', 20), ('Swift', 32)])
print(d2) # OrderedDict([('Python', 20), ('Go', 25), ('Swift', 32), ('Kotlin', 43)])
print(d1 == d2) # False

上面程序先创建了一个普通的 dict 对象,该对象中包含 4 个 key-value 对;接下来程序分别使用 sorted() 函数对 my_data(dict 对象)的 items 进行排序:d1 是按 key 排序的;d2 是按 value 排序的,这样得到的 d1、d2 两个 OrderedDict 中的 key-value 对是一样的,只不过顺序不同。
运行上面程序,可以看到如下输出结果:

OrderedDict([('Go', 25), ('Kotlin', 43), ('Python', 20), ('Swift', 32)])
OrderedDict([('Python', 20), ('Go', 25), ('Swift', 32), ('Kotlin', 43)])
False

从上面的输出结果可以看到,虽然两个 OrderedDict 所包含的 key-value 对完全相同,但由于它们的顺序不同,因此程序判断它们不相等。

2 OrderedDict的特性

由于OrderedDict是有序的,所以除了从dcit继承来的特性和操作,OrderedDict还具有自己的特性和操作。由于OrderedDict的底层实现是哈希表和双链表,所以Python为OrderedDict提供了从头部或尾部弹出节点和移动节点到头部或者尾部的两种操作。分别为:

  • popitem(last=True):默认弹出并返回最右边(最后加入)的 key-value 对;如果将 last 参数设为 False,则弹出并返回最左边(最先加入)的 key-value 对。
  • move_to_end(key, last=True):默认将指定的 key-value 对移动到最右边(最后加入);如果将 last 改为 False,则将指定的 key-value 对移动到最左边(最先加入)。
from collections import OrderedDict
d = OrderedDict.fromkeys('abcde')
# 将b对应的key-value对移动到最右边(最后加入)
d.move_to_end('b')
print(d.keys()) # odict_keys(['a', 'c', 'd', 'e', 'b'])
# 将b对应的key-value对移动到最左边(最先加入)
d.move_to_end('b', last=False)
print(d.keys()) # odict_keys(['b', 'a', 'c', 'd', 'e'])
# 弹出并返回最右边(最后加入)的key-value对
print(d.popitem()[0]) # e
# 弹出并返回最左边(最先加入)的key-value对
print(d.popitem(last=False)[0]) # b

运行上面程序,可以看到如下输出结果:

odict_keys(['a', 'c', 'd', 'e', 'b'])
odict_keys(['b', 'a', 'c', 'd', 'e'])
e
b

通过上面的输出结果可以看出,使用 OrderedDict 的 move_to_end() 方法可以方便地将指定的 key-value 对移动到 OrderedDict 的任意一端;而 popitem() 方法则可用于弹出并返回 OrderedDict 任意一端的 key-value 对。

总结

  1. 只有当两个Ordered的元素相同,并且顺序也相同的时候,两个OrderDict才相同。
  2. popitem(last = True),弹出一个元素,last为True时是从尾部删除,为False时从头部删除,默认last为True。返回的是key-val对组成的元组。
  3. move_to_end(key, last=True),一定一个元素到链表的头部或者尾部,当last为True时,移动到尾部,False时移动到头部,默认是True。

原文链接:Python OrderedDict用法详解

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值