Python字典(dict类型的对象)不保留元素的顺序;CPython从3.6开始就这样做了,但在其他实现中,这取决于实现,而且是不确定的;语言规范从3.7开始保留了这个顺序。
OrderedDict是在标准库的集合模块中提供的,是一个保留了顺序的字典。使用这个是安全的。
导入集合模块。它被包含在标准库中,不需要被安装。
import collections
如果你写了以下内容,你可以省略以下例子中的集合。
from collections import OrderedDict
以下是关于如何使用OrderedDict的描述。
- 创建一个OrderedDict对象
- OrderedDict是dict的一个子类
- 将元素移到开头或结尾
- 在任何位置添加一个新元素。
- 重新排列(重新排序)元素
- 按键或值对元素进行排序
创建一个OrderedDict对象
构造函数collection.OrderedDict()可以用来创建一个OrderedDict对象。
创建一个空的OrderedDict对象并添加值。
od = collections.OrderedDict()
od['k1'] = 1
od['k2'] = 2
od['k3'] = 3
print(od)
# OrderedDict([('k1', 1), ('k2', 2), ('k3', 3)])
也可以为构造函数指定参数。
你可以使用关键字参数、键值对的序列(如图元组(key, value)),等等。后者可以是一个列表,也可以是一个元组,只要是一个键值对。
print(collections.OrderedDict(k1=1, k2=2, k3=3))
print(collections.OrderedDict([('k1', 1), ('k2', 2), ('k3', 3)]))
print(collections.OrderedDict((['k1', 1], ['k2', 2], ['k3', 3])))
# OrderedDict([('k1', 1), ('k2', 2), ('k3', 3)])
# OrderedDict([('k1', 1), ('k2', 2), ('k3', 3)])
# OrderedDict([('k1', 1), ('k2', 2), ('k3', 3)])
在3.5版本之前,关键字参数的顺序没有被保留,但从3.6版本开始,现在被保留了。
在3.6版本中有所改变。随着PEP 468的接受,OrderedDict构造函数的顺序和传递给update()方法的关键字参数被保留下来。
collections — Container datatypes — Python 3.10.0 Documentation
普通的字典(dict类型的对象)也可以传递给构造函数,但在dict类型不保留顺序的实现中,由它生成的OrderedDict也将不保留顺序。
print(collections.OrderedDict({'k1': 1, 'k2': 2, 'k3': 3}))
# OrderedDict([('k1', 1), ('k2', 2), ('k3', 3)])
OrderedDict是dict的一个子类
OrderedDict是dict的一个子类。
print(issubclass(collections.OrderedDict, dict))
# True
OrderedDict也有与dict相同的方法,获取、改变、添加和删除元素的方法与dict相同。
print(od['k1'])
# 1
od['k2'] = 200
print(od)
# OrderedDict([('k1', 1), ('k2', 200), ('k3', 3)])
od.update(k4=4, k5=5)
print(od)
# OrderedDict([('k1', 1), ('k2', 200), ('k3', 3), ('k4', 4), ('k5', 5)])
del od['k4'], od['k5']
print(od)
# OrderedDict([('k1', 1), ('k2', 200), ('k3', 3)])
详见以下文章。
将元素移到开头或结尾
你可以使用OrderedDict自己的方法move_to_end()来将一个元素移到开头或结尾。
指定键作为第一个参数。默认是移到最后,但如果第二个参数最后一个是假的,就会移到开头。
od.move_to_end('k1')
print(od)
# OrderedDict([('k2', 200), ('k3', 3), ('k1', 1)])
od.move_to_end('k1', False)
print(od)
# OrderedDict([('k1', 1), ('k2', 200), ('k3', 3)])
在任何位置添加一个新元素。
可以创建一个新的OrderedDict对象,在任意位置添加一个新元素。具体来说,这可以在以下流程中完成。
- 用list()列出可以用items()方法获得的视图对象。
- 在列表的insert()方法中添加一个键值对的元组(key, value)。
- 通过传递给构造函数collection.OrderedDict()来创建一个新的对象。
l = list(od.items())
print(l)
# [('k1', 1), ('k2', 200), ('k3', 3)]
l.insert(1, ('kx', -1))
print(l)
# [('k1', 1), ('kx', -1), ('k2', 200), ('k3', 3)]
od = collections.OrderedDict(l)
print(od)
# OrderedDict([('k1', 1), ('kx', -1), ('k2', 200), ('k3', 3)])
insert()把要插入的位置作为第一个参数,把要插入的元素作为第二个参数。
在这个例子中,一个新的对象被分配给了原始变量,而原始对象本身没有添加新的元素。
重新排列(重新排序)元素
替换元素的过程与上面的例子相同。
- 用list()列出可以用items()方法获得的视图对象。
- 替换列表中的元素
- 通过传递给构造函数collection.OrderedDict()来创建一个新的对象。
l = list(od.items())
print(l)
# [('k1', 1), ('kx', -1), ('k2', 200), ('k3', 3)]
l[0], l[2] = l[2], l[0]
print(l)
# [('k2', 200), ('kx', -1), ('k1', 1), ('k3', 3)]
od = collections.OrderedDict(l)
print(od)
# OrderedDict([('k2', 200), ('kx', -1), ('k1', 1), ('k3', 3)])
如果你想指定一个键并替换它,使用index()方法从键的列表中获得索引(位置),如下图所示。
l = list(od.items())
k = list(od.keys())
print(k)
# ['k2', 'kx', 'k1', 'k3']
print(k.index('kx'))
# 1
l[k.index('kx')], l[k.index('k3')] = l[k.index('k3')], l[k.index('kx')]
print(l)
# [('k2', 200), ('k3', 3), ('k1', 1), ('kx', -1)]
od = collections.OrderedDict(l)
print(od)
# OrderedDict([('k2', 200), ('k3', 3), ('k1', 1), ('kx', -1)])
按键或值对元素进行排序
根据可以通过items()方法获得的视图对象,创建一个排序的键值对的图元列表(key, value),并将其传递给构造函数collection.OrderedDict()来创建一个新对象。
排序是通过指定一个匿名函数(lambda表达式)进行的,该函数从一个元组(key, value)中返回一个键或值,作为内置函数sorted()的参数key。
如果你想颠倒顺序,将sorted()的反向参数设置为true。
print(od)
# OrderedDict([('k2', 200), ('k3', 3), ('k1', 1), ('kx', -1)])
od_sorted_key = collections.OrderedDict(
sorted(od.items(), key=lambda x: x[0])
)
print(od_sorted_key)
# OrderedDict([('k1', 1), ('k2', 200), ('k3', 3), ('kx', -1)])
od_sorted_value = collections.OrderedDict(
sorted(od.items(), key=lambda x: x[1], reverse=True)
)
print(od_sorted_value)
# OrderedDict([('k2', 200), ('k3', 3), ('k1', 1), ('kx', -1)])