2012-04-04 10 views
11

tôi đang làm một hoạt động thiết lập sự khác biệt trong Python:Giữ lại trật tự trong khi sử dụng Python của bộ chênh lệch

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

tôi nhận được:

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

tôi cần để có được những yếu tố đầu tiên cho các hoạt động tiếp theo Đó là điều quan trọng. Làm cách nào để giữ lại danh sách x ở định dạng gốc?

+3

Sets là theo định nghĩa thứ tự. – icktoofay

+4

Và bạn không bao giờ nên sử dụng mô-đun 'bộ'. Sử dụng kiểu 'set' được tạo sẵn. –

+3

Loại * sets.Set * là lựa chọn hợp lý cho ai đó cần tương thích với các phiên bản cũ hơn của Python. Kiểu * set * tích hợp được mô hình hóa sau khi * sets.Set * - cả hai đều hoạt động tốt cho hầu hết các ứng dụng (mặc dù phiên bản tích hợp nhanh hơn). –

Trả lời

4

Bạn chỉ có thể làm được điều này

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

hoặc

filter(diff.__contains__, x) 
+0

Và nếu bạn làm điều đó với một số lượng lớn các thành phần trong 'y' hoặc nhiều lần, làm việc trên' set (y) 'thay vì' y' có thể nhanh hơn. –

+0

Được rồi, tôi không chắc chắn về tốc độ nhưng nếu bạn chắc chắn về nó thì tôi đoán đó là tốt nhất. – jamylak

+0

Đó là điều bạn muốn kiểm tra hiệu suất. –

11

Sets là không có thứ tự, vì vậy bạn sẽ cần phải đặt kết quả trở lại theo đúng thứ tự sau khi làm khác biệt thiết lập của bạn. May mắn thay bạn đã có các yếu tố theo thứ tự bạn muốn, vì vậy điều này rất dễ dàng.

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

Nhưng điều này có thể được sắp xếp hợp lý; bạn có thể làm sự khác biệt như là một phần của việc hiểu danh sách (mặc dù nó được cho là hơi rõ ràng rằng đó là những gì bạn đang làm).

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

Bạn thậm chí có thể làm điều đó mà không cần tạo các set từ y, nhưng set sẽ cung cấp các bài kiểm tra thành viên nhanh chóng, mà bạn sẽ tiết kiệm thời gian đáng kể nếu một trong hai danh sách là lớn.

+0

Khi bạn nói sắp xếp hợp lý, bạn có ý nghĩa gì về hiệu suất không? – jamylak

+0

nvm, figured nó phải được nhanh hơn. – jamylak

+0

Hơi nhanh hơn, vâng. Nó sẽ chỉ cần đi qua danh sách 'x' một lần thay vì hai lần. – kindall

17

Có vẻ như bạn cần một bộ đặt hàng thay vì một tập hợp thông thường.

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

Python không đi kèm với một tập có thứ tự, nhưng nó rất dễ dàng để làm một:

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) 

Hope this helps :-)