Добавить ключи в словарь в отсортированном порядке
Предположим, у меня есть словарь
{1:5, 2:5, 4:5}
есть ли структура данных такая, что если я добавлю пару ключ-значение 3:5
, чтобы он был введен в словарь, чтобы ключи были в отсортированном порядке? т. е.
{1:5, 2:5, 3:5, 4:5}
Я в курсе collections.OrderedDict()
, но это только сохраняет ключи в том порядке, в котором они были добавлены (что для меня в настоящее время недостаточно).
Я не хочу использовать обычный словарь dic = {}
, тогда придется использовать sorted(dic)[0]
хапнуть ключик. Я бы предпочел sorted_dict[0]
тип функции.
Причина этого в том, что если я использую обычный словарь, мне придется вызывать сортировку несколько раз, так как я постоянно добавляю пары в свой словарь.
EDIT: я должен был упомянуть, что это не только самые маленькие и самые большие ключи, о которых я забочусь, мне также нужно будет печатать этот словарь через регулярные промежутки времени...
3 ответов
если вы планируете добавлять и удалять ключи из словаря непрерывно, вы действительно хотите что-то, что использует соответствующую структуру данных для проблемы-не хэш-таблицу (или хэш-таблицу плюс список, как с SortedOrderedDict
-Type recipes), но сбалансированное дерево (или эквивалент, например, список пропусков).
если вы посмотрите на PyPI, вы найдете несколько вариантов. Моя рекомендация была бы blist
. Даже если его структура данных может быть не совсем оптимальной как и некоторые другие (потому что дерево B+намного шире, чем двоичное дерево), оно, вероятно, достаточно хорошо для почти любого случая использования, с которым вы столкнетесь. И он имеет полный и хорошо протестированный интерфейс, включая хорошо протестированные гарантии производительности. И он довольно часто используется в других серьезных проектах.
если вы имеете дело с одним из редких случаев, когда производительность дерева действительно критична, вы, вероятно, должны посмотреть на различные красно-черное дерево, splay tree, skiplist и т. д. реализации. Я использовал bintrees
раньше, который имеет отличный интерфейс (например, вы можете получить доступ к ключам и значениям по индексу и даже нарезать дерево, а также рассматривать его как dict
, и автор продумал и избежал всех потенциальных двусмысленностей), но я серьезно не тестировал его производительность.
или, если ваши ключи и значения действительно являются мелкими целыми числами, вы можете рассмотреть возможность использования Cython для обертывания c++ map<int, int>
в Pythonic взаимодействие. (Это не совсем возможно, чтобы обеспечить полное интерфейс поверх C++ map
, но часто это не нужно в любом случае.) Или, альтернативно, измените одну из реализаций, таких как bintrees.FastRBTree
для хранения и сравнения long
вместо PyObject*
.
С другой стороны, если вы только собираетесь создать словарь всех сразу, а затем использовать его, есть гораздо более простой ответ. Сортируйте его и вставляйте в OrderedDict
. Тогда вам не нужно ничего за пределами stdlib.
sorted_dict = collections.OrderedDict(sorted(d.iteritems()))
из комментария к другому ответу вы говорите: "у меня нет разрешений на установку новых модулей..."
во-первых, убедитесь, что это действительно правда. Вы, вероятно, do есть разрешение на установку модулей в каталоге сайта пользователя-пакеты. Или, если и/или вы используете 3.3 со встроенным venv
, еще лучше, у вас, вероятно, есть разрешение на создание venv и установку модулей в это.
но если Итак, что вам нужно сделать, это скопировать файлы из blist
/bintrees
/ что угодно в ваш проект.
проблема, с которой вы можете столкнуться, заключается в том, что большинство этих пакетов содержат модули расширения C, что означает, что вы должны иметь возможность их создавать (ну,build_ext -i
них). Если в вашей системе нет файлов python dev и цепочки инструментов компилятора, вы не можете этого сделать. В этом случае вы ищете лучшее решение pure-Python. bintrees
поставляется с реализацией pure-Python, которая идентично обычной реализации C-extension, за исключением более медленного. Это все еще O(log N), конечно, просто постоянный фактор намного выше. Если N достаточно большой, это все еще огромная победа; если нет, это может быть не так.
если какая-либо часть этого звучит разумно, но вам нужна помощь в настройке пакетов сайта для каждого пользователя или виртуального env, или копировании модуля в проект на месте, или создании расширений на месте и т. д., вы, вероятно, должны искать существующие вопросы и задавать новые, если вы не могу найти его (хотя бы потому, что люди, которые являются экспертами по вопросам установки, не обязательно являются экспертами в структурах данных и даже не могут читать этот вопрос).
попробуйте этот рецепт - http://code.activestate.com/recipes/576998-sorted-dictionary/
Он сохраняет ключи, отсортированные с помощью stdlib bisect модуль.
более чем на год опоздал на вечеринку, но я хотел предложить sortedcontainers модуль. Как blist и bintrees, он обеспечивает SortedDict тип данных, который хранит ключи в отсортированном порядке. В отличие от этих модулей он написан на чистом Python и на самом деле быстрее. SortedDict также поддерживает индексирование. Поиск min / max фактически происходит в O (1) раз.
поскольку это pure-Python, установка с pip должна быть Бриз:
pip install sortedcontainers
тогда вы можете просто импортировать SortedDict
In [1]: from sortedcontainers import SortedDict
In [2]: d = SortedDict({1:5, 2:5, 4:5})
In [3]: d
Out[3]: SortedDict({1: 5, 2: 5, 4: 5})
In [4]: d[3] = 5
In [5]: d
Out[5]: SortedDict({1: 5, 2: 5, 3: 5, 4: 5})
Если у вас возникли трудности с установкой вещей с помощью pip или не удается скопировать файлы, которые будут нуждаться в компиляции, то вы можете просто вытащить sortedlist.py и sorteddict.py файлы из хранилища. Весь код С открытым исходным кодом на github.
модуль sortedcontainers также предоставляет сравнение производительности С самыми популярными предложениями benchmarked против одного другой.