2012-07-30 32 views
9

Tôi muốn so sánh nhiều đối tượng và chỉ trả lại True nếu tất cả các đối tượng không bằng nhau. Tôi đã thử sử dụng mã bên dưới, nhưng nó không hoạt động. Nếu obj1 và obj3 bằng nhau và obj2 và obj3 không bằng nhau, kết quả là True.Python: xác định xem có bất kỳ mục nào theo thứ tự không bằng bất kỳ mục nào khác

obj1 != obj2 != obj3 

Tôi có hơn 3 đối tượng để so sánh. Sử dụng mã dưới đây là trong số câu hỏi:

all([obj1 != obj2, obj1 != obj3, obj2 != obj3]) 
+0

là số của các đối tượng cố định, hoặc biến? Chúng là các phần tử của một mảng hay trong các biến riêng lẻ? –

Trả lời

20

@Michael Câu trả lời của Hoffman là tốt nếu các đối tượng đều có thể bẻ khóa. Nếu không, bạn có thể sử dụng itertools.combinations:

>>> all(a != b for a, b in itertools.combinations(['a', 'b', 'c', 'd', 'a'], 2)) 
False 
>>> all(a != b for a, b in itertools.combinations(['a', 'b', 'c', 'd'], 2)) 
True 
18

Nếu các đối tượng đều hashable, sau đó bạn có thể xem một frozenset của chuỗi các đối tượng có chiều dài tương tự như trình tự riêng của mình:

def all_different(objs): 
    return len(frozenset(objs)) == len(objs) 

Ví dụ:

>>> all_different([3, 4, 5]) 
True 
>>> all_different([3, 4, 5, 3]) 
False 
+0

Chết tiệt! đánh bại tôi trong 10 giây. – inspectorG4dget

+1

Lưu ý rằng thao tác này sẽ không hoạt động nếu các đối tượng không thể thực hiện được. – BrenBarn

+0

Điều này không có tác dụng nếu một (hoặc tất cả) đối tượng không thể thực hiện được (ví dụ: danh sách) – mgilson

3

Bạn có thể kiểm tra tất cả các mục trong danh sách là duy nhất bằng cách chuyển đổi nó vào một bộ.

my_obs = [obj1, obj2, obj3] 
all_not_equal = len(set(my_obs)) == len(my_obs) 
4
from itertools import combinations 
all(x != y for x, y in combinations(objs, 2)) 
+1

Đó là so sánh O (n^2) - LOT cho danh sách lớn. – inspectorG4dget

6

Nếu các đối tượng là unhashable nhưng orderable (ví dụ, danh sách) sau đó bạn có thể chuyển đổi các giải pháp itertools từ O (n^2) O (n log n) bằng cách phân loại:

def all_different(*objs): 
    s = sorted(objs) 
    return all(x != y for x, y in zip(s[:-1], s[1:])) 

Dưới đây là một thực hiện đầy đủ:

def all_different(*objs): 
    try: 
     return len(frozenset(objs)) == len(objs) 
    except TypeError: 
     try: 
      s = sorted(objs) 
      return all(x != y for x, y in zip(s[:-1], s[1:])) 
     except TypeError: 
      return all(x != y for x, y in itertools.combinations(objs, 2)) 
+0

Kiểm tra tính băm là quá phức tạp (và cũng hơi sai). Cách thành ngữ để làm điều này trong Python là cố gắng xây dựng một 'frozenset()' và bắt 'TypeError' nếu điều này không thành công. (Bài kiểm tra hơi sai vì 'isinstance (obj, collections.Hashable)' là 'True' không đảm bảo đối tượng thực sự có thể băm được. Nó chỉ kiểm tra nếu đối tượng có một kiểu cho phép nguyên tắc được băm. ([],) 'như một ví dụ truy cập.) –

+0

@SvenMarnach cảm ơn, cố định. – ecatmur

Các vấn đề liên quan