Python эквивалент std:: set и std:: multimap
Я переношу программу на С++ на Python. Есть несколько мест, где он использует std::set
для хранения объектов, которые определяют свои собственные операторы сравнения. Поскольку стандартная библиотека Python не имеет эквивалента std::set
(структура данных сопоставления ключевых значений), я попытался использовать обычный словарь, а затем отсортировал его при повторении, например:
def __iter__(self):
items = self._data.items()
items.sort()
return iter(items)
Однако профилирование показало, что все вызовы от .sort()
до __cmp__
являются серьезным узким местом. Мне нужна лучшая структура данных - по существу сортированный словарь. Кто-нибудь знает о существующей реализации? В противном случае, какие-либо рекомендации о том, как я должен это реализовать? Производительность чтения важнее, чем производительность записи, а время важнее памяти.
Бонусные баллы, если он поддерживает несколько значений для каждого ключа, например С++ std::multimap
.
Обратите внимание, что класс OrderedDict
не соответствует моим потребностям, потому что он возвращает элементы в порядке вставки, тогда как они мне нужно сортировать, используя их методы __cmp__
.
Ответы
Ответ 1
Для отсортированного словаря вы можете (ab) использовать стабильную природу timsort python: в основном, сохраняйте детали частично отсортированными, добавляйте элементы в конце по мере необходимости, переключая "грязный" флаг и сортируя оставшиеся до итерации, См. Эту запись для подробностей и реализации (ответ Мартелли):
Key-ordered dict в Python
Ответ 2
Вы должны использовать sort(key=...)
.
Ключевая функция, которую вы используете, будет связана с cmp, который вы уже используете. Преимущество состоит в том, что ключевая функция называется n раз, тогда как cmp называется nlog n раз, и обычно ключ выполняет половину работы, которую выполняет cmp
Если вы можете включить свой __cmp__()
, мы можем, вероятно, показать вам, как его преобразовать в ключевую функцию
Если вы делаете много итераций между изменениями, вы должны кэшировать значение отсортированных элементов.
Ответ 3
Python не имеет встроенных структур данных для этого, хотя модуль bisect
предоставляет функциональные возможности для хранения отсортированного списка с подходящими эффективными алгоритмами.
Если у вас есть список отсортированных ключей, вы можете связать его с collections.defaultdict(list)
, чтобы обеспечить многопользовательскую функциональность.
Ответ 4
В своей книге "" Программирование на Python 3 ", Марк Саммерфилд вводит отсортированный класс словаря. Исходный код доступен в этот zip-архив - найдите SortedDict.py. Класс SortedDict подробно описан в книге (которую я очень рекомендую). Он поддерживает произвольные ключи для сравнения и несколько значений для каждого ключа (что любой словарь в Python делает, так что я не думаю, что это большая сделка).