Чому в стандартних бібліотеках Python немає відсортованих контейнерів?


84

Чи існує рішення дизайну Python (PEP), яке виключає додавання відсортованого контейнера до Python?

( OrderedDictне є відсортованим контейнером, оскільки він упорядкований за порядком вставки.)


1
як колекції.
utdemir

1
Це просто швидше. O (1) для хеш-карти проти O (log n) для впорядкованого набору.
vartec

19
@utdmr: OrderedDict сортується за порядком вставки, а не за довільним ключем, як відсортований контейнер.
Neil G

1
@ Hi-Angel Ні, це не те, що відсортований контейнер означає. Напр.
Ніл Г

1
"відсортований контейнер - це той, який сортує елементи після вставки". Не зовсім так: я б сказав, що відсортований контейнер - це контейнер, інтерфейс якого має ефективну відсортовану (за довільним ключем) ітерацію та пошук. Ваше непорозуміння випливає з вашого незвичного визначення.
Neil G

Відповіді:


77

Це свідоме дизайнерське рішення з боку Гвідо (він навіть дещо неохоче ставився до додавання collectionsмодуля). Його мета - зберегти "один очевидний спосіб зробити це", коли справа стосується вибору типів даних для додатків.

Основна концепція полягає в тому, що якщо користувач досить витончений, щоб усвідомити, що вбудовані типи не є правильним рішенням для їх проблеми, то вони також вирішують завдання пошуку відповідної сторонньої бібліотеки.

З огляду на те, що list + сортування, list + heapq і list + bisect охоплюють багато випадків використання, які в іншому випадку покладалися б на відсортовані за своєю суттю структури даних, і такі пакети, як blist, існують, немає величезного бажання додати більше складності в цей простір стандартна бібліотека.

Певним чином це схоже на той факт, що у стандартній бібліотеці немає багатовимірного масиву, а замість цього передається це завдання людям NumPy.


2
Дякую, я шукав мотивації цього дизайнерського рішення. Саме такої відповіді я шукав. Мій початковий інстинкт не мав би робити речі таким чином, але аргумент дуже переконливий.
Neil G

collections.Counterможе використовуватися як відсортований набір. Хоча це може бути неефективним.
Кодерек

1
@coderek: collections.Counterнесортований і не підходить для представлення відсортованого набору.
user2357112 підтримує Моніку

Але чи не слід хоча б сортувати вбудований словник? Словник потрібно зберігати відсортованим, щоб забезпечити швидкий доступ до елементів, мені здається дивним, що коли ви перебираєте його, ви все одно якось отримуєте невідсортовані елементи.
Hi-Angel

1
@ Hi-Angel dict- це хеш-таблиця.
Neil G

83

Існує також модуль сортованих контейнерів python, який реалізує типи сортування списку, dict та набору. Це дуже схоже на blist, але реалізовано в pure-Python і в більшості випадків швидше .

>>> from sortedcontainers import SortedSet
>>> ss = SortedSet([3, 7, 2, 2])
>>> ss
SortedSet([2, 3, 7])

Він також має функціональність, незвичну для інших пакетів:

>>> from sortedcontainers import SortedDict
>>> sd = SortedDict((num, num) for num in range(100000))
>>> sd.iloc[-5] # Lookup the fifth-to-last key.
99995

Застереження: Я є автором модуля відсортованих контейнерів.


1
Приємно! Можливо, ви захочете оновити свою документацію, щоб вказати, що основним сховищем є мотузка .
Neil G

1
@NeilG Дякую! Пара приміток: blist не написаний чистою мовою Python. Відсортовані набори, списки та типи dict базуються на типі blist, який є B + -деревом, реалізованим в C. Крім того, основна структура насправді не є мотузкою; це більше схоже на B + -дерево, але має лише один рівень вузлів.
GrantJ

3
Це насправді чудовий приклад того, як велике O може ввести в оману. Це, мабуть, сповільнило б близько трильйона елементів, але більшість людей не має терабайта пам'яті, щоб турбуватися про це. Я перевірив його на мільярди елементів, і це було так само швидко, як C-реалізації. Він також використовує набагато менше пам'яті, підтримуючи таку просту структуру на основі списків.
GrantJ

1
Так, абсолютно. Це той самий аргумент, який вони використовують для виправдання використання такого роду структури даних для рядків, особливо довгих рядків, які використовуються в редакторі.
Neil G

2
У будь-якому разі, дякую, що написали це. Буду пам’ятати, якщо мені потрібна ця структура даних.
Neil G


5

Не зовсім "відсортований контейнер", але вас може зацікавити модуль бісект стандартної бібліотеки , який "забезпечує підтримку ведення списку в відсортованому порядку без необхідності сортувати список після кожної вставки".


1

У heapqстандартній бібліотеці є a , він не точно відсортований, а такий. Також є пакет blist , але його немає у стандартній бібліотеці.


-2

Списки Python упорядковані. Якщо їх відсортувати, вони залишаться такими. У Python 2.7 OrderedDictбув доданий тип для ведення явно упорядкованого словника.

Python також має набори (колекція, в якій члени повинні бути унікальними), але за визначенням вони не впорядковані. Сортування набору просто повертає a list.


8
Дякуємо, що знайшли час відповісти. OrderedDict сортується за порядком вставки, а не за довільним ключем, як відсортований контейнер. set також не є відсортованим контейнером.
Neil G

1
Це btree, можливо, те, що ви шукаєте? stackoverflow.com/questions/628192#628432
jathanism

дякую, btree - це саме те, що я шукав. Я збираюся піти з розмиттям, оскільки це в MacPorts і має купу зручних структур даних.
Neil G,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.