¿Tiene Python un conjunto ordenado?
Python tiene un diccionario ordenado . ¿Qué pasa con un conjunto ordenado?
La respuesta es no, pero a partir de Python 3.7 puedes usar el simple dict
de la biblioteca estándar de Python con solo claves (y valores como None
) para el mismo propósito.
A continuación se muestra un ejemplo de cómo utilizar dict
un conjunto ordenado para filtrar elementos duplicados y al mismo tiempo conservar el orden, emulando así un conjunto ordenado. Utilice el dict
método de clase fromkeys()
para crear un dictado, luego simplemente solicite el keys()
reverso.
>>> keywords = ['foo', 'bar', 'bar', 'foo', 'baz', 'foo']
>>> list(dict.fromkeys(keywords))
['foo', 'bar', 'baz']
Para versiones anteriores de Python, utilice elcollections.OrderedDict
Hay una receta de conjunto ordenado (posible nuevo enlace ) para esto a la que se hace referencia en la documentación de Python 2 . Esto se ejecuta en Py2.6 o posterior y 3.0 o posterior sin ninguna modificación. La interfaz es casi exactamente la misma que la de un conjunto normal, excepto que la inicialización debe realizarse con una lista.
OrderedSet([1, 2, 3])
Este es un MutableSet, por lo que la firma .union
no coincide con la del conjunto, pero como incluye __or__
algo similar, se puede agregar fácilmente:
@staticmethod
def union(*sets):
union = OrderedSet()
union.union(*sets)
return union
def union(self, *sets):
for set in sets:
self |= set
Actualización : esta respuesta está obsoleta a partir de Python 3.7. Consulte la respuesta anterior de jrc para obtener una mejor solución. Mantendré esta respuesta aquí solo por razones históricas.
Un conjunto ordenado es funcionalmente un caso especial de un diccionario ordenado.
Las claves de un diccionario son únicas. Por lo tanto, si uno ignora los valores en un diccionario ordenado (por ejemplo, asignándolos None
), entonces esencialmente tiene un conjunto ordenado.
A partir de Python 3.1 y 2.7 existe collections.OrderedDict
. A continuación se muestra un ejemplo de implementación de un OrderedSet. (Tenga en cuenta que solo es necesario definir o anular unos pocos métodos: collections.OrderedDict
y collections.MutableSet
hacer el trabajo pesado).
import collections
class OrderedSet(collections.OrderedDict, collections.MutableSet):
def update(self, *args, **kwargs):
if kwargs:
raise TypeError("update() takes no keyword arguments")
for s in args:
for e in s:
self.add(e)
def add(self, elem):
self[elem] = None
def discard(self, elem):
self.pop(elem, None)
def __le__(self, other):
return all(e in other for e in self)
def __lt__(self, other):
return self <= other and self != other
def __ge__(self, other):
return all(e in self for e in other)
def __gt__(self, other):
return self >= other and self != other
def __repr__(self):
return 'OrderedSet([%s])' % (', '.join(map(repr, self.keys())))
def __str__(self):
return '{%s}' % (', '.join(map(repr, self.keys())))
difference = property(lambda self: self.__sub__)
difference_update = property(lambda self: self.__isub__)
intersection = property(lambda self: self.__and__)
intersection_update = property(lambda self: self.__iand__)
issubset = property(lambda self: self.__le__)
issuperset = property(lambda self: self.__ge__)
symmetric_difference = property(lambda self: self.__xor__)
symmetric_difference_update = property(lambda self: self.__ixor__)
union = property(lambda self: self.__or__)