2012-10-04 53 views
14

Các thuận tiện nhất, "Pythonic" cách để loại bỏ bản sao từ một danh sách về cơ bản là:Loại bỏ trùng lặp bằng so sánh tùy chỉnh

mylist = list(set(mylist)) 

Nhưng giả sử tiêu chí của bạn cho đếm một bản sao phụ thuộc vào một trường thành viên cụ thể của các đối tượng chứa trong mylist.

Vâng, có một giải pháp là chỉ cần xác định __eq____hash__ cho các đối tượng trong mylist, và sau đó là cổ điển list(set(mylist)) sẽ làm việc.

Nhưng đôi khi bạn có các yêu cầu kêu gọi linh hoạt hơn một chút. Sẽ rất thuận tiện khi có thể tạo các lambda trực tuyến để sử dụng các thói quen so sánh tùy chỉnh để xác định các bản sao theo các cách khác nhau. Lý tưởng nhất, một cái gì đó như:

mylist = list(set(mylist, key = lambda x: x.firstname)) 

Tất nhiên, điều đó không thực sự làm việc vì các nhà xây dựng set không mất một chức năng so sánh, và set đòi hỏi phím hashable là tốt.

Vậy cách gần nhất để đạt được điều gì đó như thế, để bạn có thể loại bỏ các bản sao bằng các hàm so sánh tùy ý?

Trả lời

19

Bạn có thể sử dụng một dict thay vì một bộ, nơi các phím của dict sẽ là giá trị duy nhất:

d = {x.firstname: x for x in mylist} 
mylist = list(d.values()) 
+0

Đó là cách dễ nhất để thực hiện điều này. Và hiệu suất sẽ gần như bằng với phương pháp thiết lập của bạn. – Chronial

+2

Wow Tôi chưa từng thấy cú pháp '{x.firstname: x for x in mylist}' trước đây. Nó được gọi là gì và tôi có thể tìm thấy nó ở đâu trong tài liệu. –

+2

@MarwanAlsabbagh: Đó là [dict comprehension] (http://www.python.org/dev/peps/pep-0274/). Nó được thêm vào trong Python 2.7 và 3.0. Nó tương đương với 'dict ((x.firstname, x) cho x trong danh sách của tôi)'. – interjay

0

tôi sẽ làm điều này:

duplicates = set() 
newlist = [] 
for item in mylist: 
    if item.firstname not in duplicates: 
     newlist.append(item) 
     excludes.add(item.firstname) 
0

Nếu bạn cần phải có sự linh hoạt hơn với nhà điều hành "trong"

def is_in(value, value_list, comparer_function): 
    """ checkes whether "value" already in "value_list" """ 
    for vi in value_list: 
     if comparer_function(vi, value): 
      return True 
    return False 

def make_unique_set(in_list, comparer_function=lambda a, b: a == b): 
    """ retusn unique set of "in_list" """ 
    new_list = [] 
    for i in in_list: 
     if not is_in(i, new_list, comparer_function): 
      new_list.append(i) 
    return new_list 

make_unique_set(mylist, comparer_function=lambda a, b : a.firstname == b.firstname) 
Các vấn đề liên quan