Đối với nhiều trường hợp sử dụng, câu trả lời bạn muốn là:
ys = set(y)
[item for item in x if item not in ys]
Đây là sự kết hợp giữa câu trả lời của aaronasterling và câu trả lời của quantumSoup .
Phiên bản của aaronasterling thực hiện len(y)
so sánh vật phẩm cho từng yếu tố x
, vì vậy phải mất thời gian bậc hai. Phiên bản của quantumSoup sử dụng các tập hợp, do đó, nó thực hiện tra cứu tập hợp thời gian không đổi duy nhất cho từng phần tử trong Tập tin x
, bởi vì nó chuyển đổi cả hai x
và y
thành tập hợp, nó làm mất thứ tự các phần tử của bạn.
Bằng cách chuyển đổi chỉ y
thành một tập hợp và lặp lại x
theo thứ tự, bạn sẽ có được thời gian tuyến tính tốt nhất của cả hai thế giới và bảo toàn trật tự. *
Tuy nhiên, điều này vẫn có một vấn đề từ phiên bản của quantumSoup: Nó yêu cầu các yếu tố của bạn có thể được băm. Điều đó được xây dựng khá nhiều vào bản chất của các bộ. ** Nếu bạn đang cố gắng, ví dụ, trừ một danh sách các ký hiệu từ một danh sách các ký tự khác, nhưng danh sách để trừ là lớn, bạn sẽ làm gì?
Nếu bạn có thể trang trí các giá trị của mình theo một cách nào đó mà chúng có thể băm được, điều đó sẽ giải quyết được vấn đề. Ví dụ: với một từ điển phẳng có giá trị tự băm:
ys = {tuple(item.items()) for item in y}
[item for item in x if tuple(item.items()) not in ys]
Nếu các loại của bạn phức tạp hơn một chút (ví dụ: thường thì bạn đang xử lý các giá trị tương thích JSON, có thể băm hoặc liệt kê hoặc các ký tự có giá trị đệ quy cùng loại), bạn vẫn có thể sử dụng giải pháp này. Nhưng một số loại không thể chuyển đổi thành bất cứ thứ gì có thể băm được.
Nếu các mục của bạn không và không thể được tạo ra, có thể băm, nhưng chúng có thể so sánh được, thì ít nhất bạn có thể có được thời gian log-linear ( O(N*log M)
, tốt hơn rất nhiều so với O(N*M)
thời gian của giải pháp danh sách, nhưng không tốt bằng các O(N+M)
thời điểm các giải pháp quy định) bằng cách phân loại và sử dụng bisect
:
ys = sorted(y)
def bisect_contains(seq, item):
index = bisect.bisect(seq, item)
return index < len(seq) and seq[index] == item
[item for item in x if bisect_contains(ys, item)]
Nếu các mục của bạn không thể băm hay so sánh được, thì bạn bị mắc kẹt với giải pháp bậc hai.
* Lưu ý rằng bạn cũng có thể thực hiện việc này bằng cách sử dụng một cặp OrderedSet
đối tượng mà bạn có thể tìm thấy công thức nấu ăn và mô-đun của bên thứ ba. Nhưng tôi nghĩ điều này đơn giản hơn.
** Lý do thiết lập tra cứu là thời gian không đổi là tất cả những gì phải làm là băm giá trị và xem liệu có mục nào cho hàm băm đó không. Nếu nó không thể băm giá trị, điều này sẽ không hoạt động.