Словари Python (объекты типа dict) не сохраняют порядок элементов; CPython делает это с версии 3.6, но это зависит от реализации и неопределенно в других реализациях; спецификация языка сохраняет порядок с версии 3.7.
OrderedDict предоставляется в модуле collections стандартной библиотеки как словарь, сохраняющий порядок. Безопасно использовать именно его.
Импортируйте модуль коллекций. Он включен в стандартную библиотеку и не требует установки.
import collections
Если вы пишете следующее, вы можете опустить коллекции. в следующих примерах.
from collections import OrderedDict
Ниже описано, как использовать OrderedDict.
- Создание объекта OrderedDict
- OrderedDict является подклассом dict
- Перемещение элементов в начало или конец
- Добавьте новый элемент в любую позицию.
- Перестановка (переупорядочивание) элементов
- Сортировка элементов по ключу или значению
Создание объекта OrderedDict
Конструктор collections.OrderedDict() может быть использован для создания объекта OrderedDict.
Создайте пустой объект OrderedDict и добавьте значения.
od = collections.OrderedDict()
od['k1'] = 1
od['k2'] = 2
od['k3'] = 3
print(od)
# 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)]))
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() для перемещения элемента в начало или конец.
Укажите ключ в качестве первого аргумента. По умолчанию выполняется перемещение в конец, но если второй аргумент last равен false, то будет выполнено перемещение в начало.
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 с новым элементом, добавленным в произвольную позицию. В частности, это можно сделать следующим образом.
- Перечислите объекты представления, которые можно получить с помощью метода items(), используя list().
- Добавьте кортеж (ключ, значение) пар ключ-значение в метод insert() списка
- Создайте новый объект, передав его конструктору collections.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() указывает позицию для вставки в качестве первого аргумента, а элемент для вставки — в качестве второго аргумента.
В примере исходной переменной присваивается новый объект, а к самому исходному объекту не добавляется никаких новых элементов.
Перестановка (переупорядочивание) элементов
Замена элементов — это тот же процесс, что и в приведенном выше примере.
- Перечислите объекты представления, которые можно получить с помощью метода items(), используя list().
- Замена элементов в списке
- Создайте новый объект, передав его конструктору collections.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)])
Сортировка элементов по ключу или значению
Создайте список кортежей (key, value) отсортированных пар ключ-значение на основе объекта представления, который можно получить методом items(), и передайте его конструктору collections.OrderedDict() для создания нового объекта.
Сортировка выполняется путем указания анонимной функции (лямбда-выражения), которая возвращает ключ или значение из кортежа (ключ, значение) в качестве аргумента key встроенной функции sorted().
Если вы хотите изменить порядок, установите аргумент reverse в 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)])