¿Tiene Python un conjunto ordenado?

Resuelto Casebash asked hace 15 años • 16 respuestas

Python tiene un diccionario ordenado . ¿Qué pasa con un conjunto ordenado?

Casebash avatar Oct 31 '09 17:10 Casebash
Aceptado

La respuesta es no, pero a partir de Python 3.7 puedes usar el simple dictde 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 dictun conjunto ordenado para filtrar elementos duplicados y al mismo tiempo conservar el orden, emulando así un conjunto ordenado. Utilice el dictmé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

jrc avatar Dec 06 '2018 18:12 jrc

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 .unionno 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
Casebash avatar Oct 31 '2009 10:10 Casebash

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.OrderedDicty collections.MutableSethacer 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__)
Stephan202 avatar Oct 31 '2009 10:10 Stephan202