2012-04-04 3 views
11

Я делаю операцию установить разницу в 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))) 

Я получаю:

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

Мне нужно, чтобы получить первый элемент для следующей операции что важно. Как сохранить список x в оригинальном формате?

+3

Наборов по определению неупорядоченного. – icktoofay

+4

И вы никогда не должны использовать модуль 'sets'. Используйте встроенный тип 'set'. –

+3

Тип * sets.Set * является разумным выбором для тех, кто нуждается в совместимости со старыми версиями Python. Тип встроенного * set * был смоделирован после * sets.Set * - оба они отлично работают для большинства приложений (хотя встроенная версия работает быстрее). –

ответ

4

Вы можете просто сделать это

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

или

filter(diff.__contains__, x) 
+0

И если вы делаете это с большим количеством элементов в 'y' или много раз, работа над' set (y) ', а не' y' может быть быстрее. –

+0

Хорошо, я не был уверен в скорости, но если вы уверены в этом, я думаю, это лучше. – jamylak

+0

Это то, что вы хотели бы проверить. –

11

Наборы неупорядоченные, так что вам нужно будет поместить результаты обратно в правильном порядке, после выполнения вашего набора разницы. К счастью, у вас уже есть элементы в нужном порядке, так что это легко.

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

Но это может быть обтекаемо; вы можете сделать разницу как часть понимания списка (хотя, возможно, немного менее ясно, что это то, что вы делаете).

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

Вы могли бы это сделать даже без создания set из y, но set обеспечит быструю проверку принадлежности, которые будут вам сэкономить много времени, если либо список большой.

+0

Когда вы говорите обтекаемое, вы имеете в виду в исполнении? – jamylak

+0

nvm, полагал, что он должен быть быстрее. – jamylak

+0

Чуть быстрее, да. Это нужно будет просто перебирать список 'x' один раз, а не дважды. – kindall

17

Похоже, вам нужен упорядоченный набор вместо обычного набора.

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

Python не приходит с упорядоченным набором, но это легко сделать один:

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) 

Надеется, что это помогает :-)

Смежные вопросы