¿Por qué no hay contenedores ordenados en las bibliotecas estándar de Python?

81

¿Existe una decisión de diseño de Python (PEP) que impida que se agregue un contenedor ordenado a Python?

( OrderedDictno es un contenedor ordenado ya que está ordenado por orden de inserción).

Neil G
fuente
1
como colecciones.OrderedDict?
utdemir
1
Simplemente es más rápido. O (1) para hashmap vs O (log n) para conjunto ordenado.
vartec
18
@utdmr: OrderedDict se ordena por orden de inserción, no por una clave arbitraria, como un contenedor ordenado.
Neil G
1
@ Hi-Angel No, eso no es lo que significa contenedor clasificado . Por ejemplo
Neil G
1
"contenedor ordenado es aquel que ordena los elementos al insertarlos". No exactamente: yo diría que un contenedor ordenado es un contenedor cuya interfaz tiene una iteración y búsqueda ordenada eficientemente (de acuerdo con una clave arbitraria). Tu malentendido proviene de tu definición inusual.
Neil G

Respuestas:

76

Es una decisión de diseño consciente por parte de Guido (incluso se mostró algo reacio con respecto a la adición del collectionsmódulo). Su objetivo es preservar "una forma obvia de hacerlo" cuando se trata de la selección de tipos de datos para aplicaciones.

El concepto básico es que si un usuario es lo suficientemente sofisticado como para darse cuenta de que los tipos integrados no son la solución adecuada para su problema, entonces también está a la altura de la tarea de encontrar una biblioteca de terceros adecuada.

Dado que list + sorting, list + heapq y list + bisect cubren muchos de los casos de uso que de otra manera se basarían en estructuras de datos ordenadas inherentemente, y existen paquetes como blist, no hay un gran impulso para agregar más complejidad en este espacio para la biblioteca estándar.

De alguna manera, es similar al hecho de que no hay una matriz multidimensional en la biblioteca estándar, sino que cede esa tarea a la gente de NumPy.

ncoghlan
fuente
2
Gracias, estaba buscando las motivaciones detrás de esta decisión de diseño. Este es exactamente el tipo de respuesta que estaba buscando. Mi instinto inicial no habría sido hacer las cosas de esta manera, pero el argumento es muy convincente.
Neil G
collections.Counterse puede utilizar como conjunto ordenado. Aunque puede que no sea eficaz.
Coderek
1
@coderek: collections.Counterno está ordenado y no es apropiado para representar un conjunto ordenado.
user2357112 apoya a Monica el
Pero, ¿no se debería ordenar al menos el diccionario integrado? El diccionario debe almacenarse ordenado para proporcionar un acceso rápido a los elementos, me parece extraño que cuando lo iteras, de alguna manera termines con elementos sin clasificar.
Hi-Angel
1
@ Hi-Angel dictes una tabla hash.
Neil G
80

También hay un módulo de contenedores ordenados de Python que implementa tipos ordenados de lista, dictado y conjunto. Es muy similar a blist pero implementado en Python puro y en la mayoría de los casos más rápido .

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

También tiene una funcionalidad poco común en otros paquetes:

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

Descargo de responsabilidad: soy el autor del módulo sortedcontainers.

GrantJ
fuente
1
¡Agradable! Es posible que desee considerar actualizar su documentación para especificar que el almacenamiento subyacente es una cuerda .
Neil G
1
@NeilG ¡Gracias! Notas de pareja: blist no está escrito en Python puro. Los tipos de conjunto, lista y dictado ordenados se basan en el tipo blist, que es un árbol B + implementado en C. Además, la estructura subyacente no es realmente una cuerda; es más similar a un árbol B + pero solo tiene un nivel de nodos.
GrantJ
3
En realidad, es un gran ejemplo de lo engañoso que puede ser la gran O. Probablemente se ralentizaría alrededor de un billón de elementos, pero la mayoría de las personas no tienen un terabyte de memoria para preocuparse por eso. Lo probé en miles de millones de elementos y fue tan rápido como las implementaciones C. También usa mucha menos memoria al mantener una estructura tan simple basada en listas.
GrantJ
1
Si absolutamente. Es el mismo argumento que usan para justificar el uso de este tipo de estructura de datos para cadenas, especialmente cadenas largas que se usan en un editor.
Neil G
2
De todos modos, gracias por escribir esto. Lo tendré en cuenta si necesito esta estructura de datos.
Neil G
11

También está el módulo blist que contiene un tipo de datos de conjunto ordenado :

sortedset(iterable=(), key=None)

>>> from blist import sortedset
>>> my_set = sortedset([3,7,2,2])
sortedset([2, 3, 7]
Adrian
fuente
5

No es exactamente un "contenedor ordenado", pero puede que le interese el módulo bisecto de la biblioteca estándar , que "proporciona soporte para mantener una lista en orden ordenado sin tener que ordenar la lista después de cada inserción".

Steven
fuente
1

Hay un heapqen la biblioteca estándar, no está exactamente ordenado, pero es un poco. También hay un paquete blist , pero no está en la biblioteca estándar.

abad
fuente
-2

Las listas de Python están ordenadas. Si los clasifica, se quedan así. En Python 2.7 OrderedDictse agregó un tipo para mantener un diccionario ordenado explícitamente.

Python también tiene conjuntos (una colección en la que los miembros deben ser únicos), pero por definición no están ordenados. Ordenar un conjunto solo devuelve un list.

jatismo
fuente
8
Gracias por tomarse el tiempo para responder. OrderedDict se ordena por orden de inserción en lugar de por una clave arbitraria como un contenedor ordenado. set tampoco es un contenedor ordenado.
Neil G
1
¿Es btree quizás lo que estás buscando? stackoverflow.com/questions/628192#628432
jathanism
gracias, btree es exactamente el tipo de cosas que estaba buscando. Voy a ir con blist ya que está en MacPorts y tiene un montón de estructuras de datos útiles.
Neil G