2012-04-04 3 views
11
Pythons Einstelldifferenzdruck mit

ich einen Satz Differenzoperation in Python so mache:Halte Ordnung während

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))) 

Ich erhalte:

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

Ich brauche das erste Element für die nächste Operation zu erhalten Was wichtig ist. Wie kann ich die Liste x im Originalformat behalten?

+3

Sets per Definition sind ungeordnet. – icktoofay

+4

Und Sie sollten niemals das Modul 'sets' verwenden. Verwenden Sie den eingebauten 'set' Typ. –

+3

Der * sets.Set * -Typ ist eine sinnvolle Wahl für jemanden, der Kompatibilität mit älteren Versionen von Python benötigt. Der eingebaute * set * -Typ wurde nach * sets.Set * modelliert - beide funktionieren für die meisten Anwendungen (obwohl die eingebaute Version schneller ist). –

Antwort

4

könnten Sie tun gerade diese

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

oder

filter(diff.__contains__, x) 
+0

Und wenn Sie es mit einer großen Anzahl von Elementen in 'y' oder vielen Male tun, kann die Arbeit an' set (y) 'anstatt' y' schneller sein. –

+0

In Ordnung, ich war mir nicht sicher über die Geschwindigkeit, aber wenn Sie sich sicher sind, dann denke ich, dass das das Beste ist. – jamylak

+0

Es ist etwas, was Sie Leistung überprüfen möchten. –

11

Sets ungeordnet sind, so dass Sie die Ergebnisse wieder in die richtige Reihenfolge gebracht werden müssen, nach dem Satz Unterschied machen. Glücklicherweise haben Sie die Elemente bereits in der von Ihnen gewünschten Reihenfolge, also ist dies einfach.

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

Aber das kann gestrafft werden; Sie können den Unterschied als Teil des Listenverständnisses machen (obwohl es wohl etwas weniger klar ist, dass Sie das tun).

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

Sie könnten es sogar tun, ohne den set von y zu schaffen, aber die set wird schnell Mitgliedschaft Tests geben, die Sie viel Zeit sparen, wenn eine Liste groß ist.

+0

Wenn Sie stromlinienförmig sagen, meinen Sie in der Leistung? – jamylak

+0

nvm, dachte, es muss schneller sein. – jamylak

+0

Etwas schneller, ja. Es muss nur einmal die Liste "x" statt zweimal durchlaufen. – kindall

17

Es sieht so aus, als ob Sie einen geordneten Satz anstelle eines regulären Satzes benötigen.

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

Python kommt nicht mit einer geordneten Menge, aber es ist leicht zu machen:

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) 

hoffe, das hilft :-)