Как использовать OrderedDict, упорядоченный словарь Python.

Бизнес

Словари 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 с новым элементом, добавленным в произвольную позицию. В частности, это можно сделать следующим образом.

  1. Перечислите объекты представления, которые можно получить с помощью метода items(), используя list().
  2. Добавьте кортеж (ключ, значение) пар ключ-значение в метод insert() списка
  3. Создайте новый объект, передав его конструктору 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() указывает позицию для вставки в качестве первого аргумента, а элемент для вставки — в качестве второго аргумента.

В примере исходной переменной присваивается новый объект, а к самому исходному объекту не добавляется никаких новых элементов.

Перестановка (переупорядочивание) элементов

Замена элементов — это тот же процесс, что и в приведенном выше примере.

  1. Перечислите объекты представления, которые можно получить с помощью метода items(), используя list().
  2. Замена элементов в списке
  3. Создайте новый объект, передав его конструктору 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)])