2012-04-04 6 views
11

que estoy haciendo una operación de conjunto diferencia en Python:orden de retención durante el uso de diferencia de conjuntos de Python

from sets import Set 
from mongokit import ObjectId 
x = [ObjectId("4f7aba8a43f1e51544000006"), ObjectId("4f7abaa043f1e51544000007"), ObjectId("4f7ac02543f1e51a44000001")] 
y = [ObjectId("4f7acde943f1e51fb6000003")] 
print list(Set(x).difference(Set(y))) 

que estoy recibiendo:

[ObjectId('4f7abaa043f1e51544000007'), ObjectId('4f7ac02543f1e51a44000001'), ObjectId('4f7aba8a43f1e51544000006')] 

que necesito para obtener el primer elemento para la próxima operación lo cual es importante. ¿Cómo puedo conservar la lista x en el formato original?

+3

Los conjuntos son, por definición, no ordenada. – icktoofay

+4

Y nunca deberías estar usando el módulo 'sets'. Use el tipo de 'conjunto' incorporado. –

+3

El tipo * sets.Set * es una elección razonable para alguien que necesita compatibilidad con versiones anteriores de Python. El tipo * set * incorporado se modeló después de * sets.Set *: ambos funcionan bien para la mayoría de las aplicaciones (aunque la versión incorporada es más rápida). –

Respuesta

4

Se podía hacer esta

diff = set(x) - set(y) 
[item for item in x if item in diff] 

o

filter(diff.__contains__, x) 
+0

Y si lo haces con una gran cantidad de elementos en 'y' o muchas veces, trabajar en' conjunto (y) 'en vez de' y' puede ser más rápido. –

+0

De acuerdo, no estaba seguro de la velocidad, pero si está seguro, entonces creo que es lo mejor. – jamylak

+0

Es algo que querrá comprobar el rendimiento de. –

11

Los conjuntos son desordenada, por lo que tendrá que poner los resultados de nuevo en el orden correcto después de hacer su diferencia de conjuntos. Afortunadamente ya tienes los elementos en el orden que quieres, así que esto es fácil.

diff = set(x) - set(y) 
result = [o for o in x if o in diff] 

Pero esto se puede racionalizar; usted puede hacer la diferencia como parte de la comprensión de la lista (aunque podría decirse que es un poco menos claro que eso es lo que está haciendo).

sety = set(y) 
result = [o for o in x if o not in sety] 

incluso se podría hacerlo sin crear el set de y, pero el set proporcionará pruebas de miembros rápidos, lo que le ahorrará tiempo significativo, si bien la lista es grande.

+0

Cuando dice simplificado, ¿quiere decir en rendimiento? – jamylak

+0

nvm, calculó que debe ser más rápido. – jamylak

+0

Un poco más rápido, sí. Solo necesitará atravesar la lista 'x' una vez en lugar de dos veces. – kindall

17

Parece que necesita un conjunto ordenado en lugar de un conjunto normal.

>>> x = [ObjectId("4f7aba8a43f1e51544000006"), ObjectId("4f7abaa043f1e51544000007"), ObjectId("4f7ac02543f1e51a44000001")] 
>>> y = [ObjectId("4f7acde943f1e51fb6000003")] 
>>> print list(OrderedSet(x) - OrderedSet(y)) 
[ObjectId("4f7aba8a43f1e51544000006"), ObjectId("4f7abaa043f1e51544000007"), ObjectId("4f7ac02543f1e51a44000001")] 

Python no viene con un conjunto ordenado, pero es fácil de hacer uno:

import collections 

class OrderedSet(collections.Set): 

    def __init__(self, iterable=()): 
     self.d = collections.OrderedDict.fromkeys(iterable) 

    def __len__(self): 
     return len(self.d) 

    def __contains__(self, element): 
     return element in self.d 

    def __iter__(self): 
     return iter(self.d) 

Esperanza esto ayuda :-)

Cuestiones relacionadas