cập nhật ::: bài đăng chứa tham chiếu đến các cáo buộc sai về hiệu suất kém của các tập so với hàng chục người. Tôi duy trì rằng nó vẫn còn hợp lý để sử dụng một frozenset trong trường hợp này, mặc dù không cần phải băm các thiết lập chính nó, chỉ vì nó đúng ngữ nghĩa hơn. Mặc dù, trong thực tế, tôi có thể không bận tâm việc gõ thêm 6 ký tự. Tôi không cảm thấy có động lực để đi qua và chỉnh sửa bài đăng, vì vậy, chỉ cần được thông báo rằng liên kết "cáo buộc" liên kết đến một số thử nghiệm không chính xác. Các chi tiết gory được băm ra trong các ý kiến. ::: cập nhật
Các đoạn thứ hai của mã posted bởi Brandon Craig Rhodes là khá tốt, nhưng khi ông không trả lời đề nghị của tôi về việc sử dụng một frozenset (tốt, không phải khi tôi bắt đầu viết những dòng này, dù sao) , Tôi sẽ tiếp tục và tự đăng nó lên.
Toàn bộ cơ sở của cam kết trong tầm tay là kiểm tra xem mỗi chuỗi giá trị (L1
) có trong bộ giá trị khác không; tập hợp các giá trị đó là nội dung của L2
và L3
. Việc sử dụng từ "set" trong câu đó là: mặc dù L2
và L3
là list
s, chúng tôi không thực sự quan tâm đến các thuộc tính giống như danh sách của chúng, như thứ tự giá trị của chúng hoặc số lượng của chúng chứa. Chúng tôi chỉ quan tâm đến số đặt (có một lần nữa) các giá trị mà chúng chứa chung.
Nếu bộ giá trị đó được lưu trữ dưới dạng danh sách, bạn phải xem từng phần tử một danh sách, kiểm tra từng phần tử. Nó tương đối tốn thời gian, và đó là ngữ nghĩa xấu: một lần nữa, nó là một "bộ" các giá trị, không phải là một danh sách. Vì vậy, Python có các loại thiết lập gọn gàng giữ một loạt các giá trị duy nhất, và có thể nhanh chóng cho bạn biết nếu một số giá trị là trong họ hay không. Điều này hoạt động khá giống với cách mà các loại dict
của python hoạt động khi bạn đang tìm kiếm một khóa.
Sự khác biệt giữa bộ và frozensets là các bộ có thể thay đổi, có nghĩa là chúng có thể được sửa đổi sau khi tạo. Tài liệu trên cả hai loại là here.
Vì tập hợp chúng ta cần tạo, liên kết của các giá trị được lưu trữ trong L2
và L3
, sẽ không bị sửa đổi khi được tạo, phù hợp ngữ nghĩa để sử dụng loại dữ liệu không thay đổi. Điều này cũng có một số lợi ích hiệu suất. Vâng, nó có ý nghĩa rằng nó sẽ có một số lợi thế; nếu không, tại sao Python có frozenset
làm nội trang dựng sẵn?
cập nhật ...
Brandon đã trả lời câu hỏi này: lợi thế thực sự của bộ đông lạnh là tính bất biến của họ làm cho nó có thể cho họ được hashable, cho phép họ được phím từ điển hoặc các thành viên của bộ khác .
Tôi đã chạy một số thử nghiệm định thời không chính thức so sánh tốc độ tạo và tra cứu các tập hợp có thể thay đổi và có thể thay đổi tương đối lớn (3000 phần tử); không có nhiều khác biệt. Điều này mâu thuẫn với liên kết trên, nhưng hỗ trợ những gì Brandon nói về chúng giống hệt nhau nhưng đối với khía cạnh của sự biến đổi.
... cập nhật
Bây giờ, vì frozensets là không thay đổi, họ không có một phương pháp cập nhật. Brandon đã sử dụng phương pháp set.update
để tránh tạo và sau đó loại bỏ danh sách tạm thời trên đường để thiết lập tạo; Tôi sẽ đi theo một cách tiếp cận khác.
items = (item for lst in (L2, L3) for item in lst)
generator expression Điều này làm cho items
một iterator qua, liên tục, nội dung của L2
và L3
. Không chỉ vậy, nhưng nó làm nó mà không tạo ra một danh sách toàn bộ các đối tượng trung gian. Sử dụng các biểu thức lồng nhau for
trong các trình tạo là một chút khó hiểu, nhưng tôi quản lý để giữ cho nó được sắp xếp bằng cách nhớ rằng chúng lồng nhau theo thứ tự mà chúng sẽ nếu bạn viết thực tế cho các vòng lặp, ví dụ:
def get_items(lists):
for lst in lists:
for item in lst:
yield item
Đó generator function tương đương với khái niệm máy phát điện mà chúng ta gán cho items
. Vâng, ngoại trừ đó là một định nghĩa hàm parametrized thay vì gán trực tiếp cho một biến.
Dù sao, đủ tiêu hóa. Thỏa thuận lớn với máy phát điện là họ không thực sự làm bất cứ điều gì. Vâng, ít nhất là không phải ngay lập tức: họ chỉ cần thiết lập công việc để được thực hiện sau, khi biểu thức máy phát điện là lặp lại. Đây chính thức được gọi là lười biếng. Chúng tôi sẽ làm điều đó (tốt, tôi, dù sao) bằng cách đi qua items
đến chức năng frozenset
, lặp lại trên nó và trả về một frozenset lạnh giá lạnh.
unwanted = frozenset(items)
Bạn thực sự có thể kết hợp hai dòng cuối cùng, bằng cách đặt các biểu hiện phát ngay trong các cuộc gọi đến frozenset
:
unwanted = frozenset(item for lst in (L2, L3) for item in lst)
lừa cú pháp gọn gàng này hoạt động miễn là iterator tạo ra bởi sự biểu hiện máy phát điện là tham số duy nhất cho hàm bạn đang gọi. Nếu không, bạn phải viết nó trong bộ ngoặc đơn riêng biệt thông thường của nó, giống như bạn đang truyền một bộ tuple làm đối số cho hàm.
Bây giờ, chúng tôi có thể tạo danh sách mới giống như cách mà Brandon đã làm, với list comprehension. Chúng sử dụng cú pháp tương tự như biểu thức trình tạo, và về cơ bản giống nhau, ngoại trừ chúng là eager thay vì lười biếng (một lần nữa, đây là các thuật ngữ kỹ thuật thực tế), vì vậy chúng có quyền làm việc lặp lại các mục và tạo một danh sách từ họ.
L4 = [item for item in L1 if item not in unwanted]
Điều này tương đương với việc chuyển biểu thức máy phát đến list
, ví dụ:
L4 = list(item for item in L1 if item not in unwanted)
nhưng thành ngữ hơn.
Vì vậy, đây sẽ tạo ra danh sách L4
, có chứa các yếu tố của L1
mà không ở một trong hai L2
hoặc L3
, duy trì thứ tự mà họ đã được ban và số lượng với họ rằng ở đó.
Nếu bạn chỉ muốn biết mà giá trị trong L1
nhưng không phải trong L2
hoặc L3
, nó dễ dàng hơn nhiều: bạn chỉ cần tạo mà thiết lập:
L1_unique_values = set(L1) - unwanted
Bạn có thể tạo một danh sách ra của nó, as does st0le, nhưng điều đó có thể không thực sự là những gì bạn muốn. Nếu bạn thực sự làm muốn thiết các giá trị mà chỉ được tìm thấy trong L1
, bạn có thể có một lý do rất tốt để giữ cho rằng thiết như một set
, hoặc thực sự một frozenset
:
L1_unique_values = frozenset(L1) - unwanted
... Annnnd, bây giờ cho một cái gì đó hoàn toàn khác nhau:
from itertools import ifilterfalse, chain
L4 = list(ifilterfalse(frozenset(chain(L2, L3)).__contains__, L1))
Không có cách nào chính xác để thực hiện việc này cho đến khi bạn quyết định xem bạn có quan tâm hay không quan tâm đến các bản sao và đặt hàng. Có lẽ một số loại danh sách hiểu hoặc thiết lập công việc tùy thuộc vào những gì bạn quan tâm. – istruble
Ngoài ra, có thể giả định rằng tất cả các mục trong danh sách sẽ có thể băm tất cả thời gian không? Nếu không, hoặc đôi khi không, điều đó rất có ý nghĩa. – martineau
Tại sao bạn không sử dụng bộ để bắt đầu? Sau đó, "số học" của bạn sẽ hoạt động. – poke