2012-04-04 5 views
11

robię operację różnicy zbiorów w Pythonie:rozkaz ustalający podczas korzystania z Pythona ustawioną różnicę

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

Dostaję:

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

muszę zdobyć pierwszy element następnej operacji co jest ważne. Jak mogę zachować listę x w oryginalnym formacie?

+3

Zestawy są z definicji nieuporządkowanej. – icktoofay

+4

I nigdy nie powinieneś używać modułu 'sets'. Użyj wbudowanego 'set' type. –

+3

Typ * sets.Set * to rozsądny wybór dla osób wymagających zgodności ze starszymi wersjami języka Python. Wbudowany * zestaw * został zamodelowany po * sets.Set * - oba działają dobrze dla większości aplikacji (choć wbudowana wersja jest szybsza). –

Odpowiedz

4

Można po prostu zrobić to

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

lub

filter(diff.__contains__, x) 
+0

A jeśli zrobisz to z dużą liczbą elementów w 'y' lub wiele razy, praca nad' set (y) 'zamiast' y' może być szybsza. –

+0

W porządku, nie byłem pewien szybkości, ale jeśli jesteś tego pewien, to myślę, że to jest najlepsze. – jamylak

+0

To jest coś, co chcesz sprawdzić wydajność. –

11

Zestawy są nieuporządkowane, więc trzeba będzie umieścić wyniki z powrotem w prawidłowej kolejności po zadanej różnicy robi swoje. Na szczęście masz już elementy w żądanej kolejności, więc jest to łatwe.

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

Ale można to usprawnić; możesz zrobić różnicę w ramach rozumienia listy (choć prawdopodobnie trochę mniej jasne, że to właśnie robisz).

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

Można nawet zrobić bez tworzenia set z y, ale set zapewni szybki testy członkostwa, które pozwoli Ci zaoszczędzić dużo czasu albo jeśli lista jest duża.

+0

Kiedy mówisz opływowo, masz na myśli wydajność? – jamylak

+0

nvm, doszedł do wniosku, że musi być szybszy. – jamylak

+0

Nieco szybciej, tak. Będzie musiał tylko raz przejść przez listę 'x' zamiast dwukrotnie. – kindall

17

Wygląda na to, że potrzebny jest uporządkowany zestaw zamiast zwykłego zestawu.

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

Python nie pochodzą z uporządkowanego zbioru, ale łatwo jest zrobić jeden:

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) 

Nadzieja to pomaga :-)

Powiązane problemy