2010-09-24 26 views
55

Trong một số mã của tôi, tôi đặt một loạt các đối tượng trong danh sách và tôi xây dựng danh sách bổ sung ngoài thuộc tính của chúng, là một chuỗi. Tôi cần phải xác định xem tất cả các mục trong danh sách thứ hai này có cùng giá trị chính xác, không biết trước giá trị của nó, và trả về một bool để tôi có thể thực hiện những điều khác nhau trong mã tùy thuộc vào kết quả.Python: xác định xem tất cả các mục trong danh sách có cùng một mục hay không

Tôi không thể biết tên của các thuộc tính trước đó, đó là lý do tại sao tôi đang cố gắng làm một cái gì đó chung chung nhất có thể.

Để làm ví dụ rõ ràng, một chức năng lý tưởng, được gọi là "all_same" sẽ làm việc như thế này:

>>> property_list = ["one", "one", "one"] 
>>> all_same(property_list) 
True 
>>> property_list = ["one", "one", "two"] 
>>> all_same(property_list) 
False 

Tôi đã nghĩ đến việc thực hiện một danh sách các yếu tố độc đáo và sau đó kiểm tra nếu chiều dài của nó là 1, nhưng Tôi không chắc đó có phải là giải pháp thanh lịch nhất ngoài kia không.

+0

Chỉ nhận ra rằng tôi đã hỏi cùng một câu hỏi tại đây: http://stackoverflow.com/questions/3844801/check-if-all-elements-in-a-list-are-identical. Làm thế nào để tôi liên kết hai câu hỏi này? – max

+0

Heh, câu hỏi đầu tiên tôi đã nhìn thấy một câu hỏi trước đó là bản sao. Thời gian đôi khi làm việc ngược lại. – wheaties

Trả lời

102
def all_same(items): 
    return all(x == items[0] for x in items) 

Ví dụ:

>>> def all_same(items): 
...  return all(x == items[0] for x in items) 
... 
>>> property_list = ["one", "one", "one"] 
>>> all_same(property_list) 
True 
>>> property_list = ["one", "one", "two"] 
>>> all_same(property_list) 
False 
>>> all_same([]) 
True 
+0

Rất đẹp, tôi sẽ sử dụng cái này, cảm ơn! – Einar

+22

'len (set (items)) == 1' nhanh hơn. – JulienD

+1

@muraveill Điều đó sẽ phụ thuộc rất nhiều vào đầu vào. – FogleBird

41

Bạn có thể lừa gạt và sử dụng set:

def all_same(items): 
    return len(set(items)) == 1 #== len(items) 

hoặc bạn có thể sử dụng:

def all_same(items): 
    return all(map(lambda x: x == items[0], items)) 

hoặc nếu bạn đang làm việc với một iterable thay vì một danh sách:

def all_same(iterable): 
    it_copy = tee(iterable, 1) 
    return len(set(it_copy)) == 1 
+0

Tập hợp sẽ chỉ có một mục, danh sách sẽ có N. – FogleBird

+1

Bạn có thể sử dụng biểu thức trình tạo trong mã thứ hai. 'tất cả (x == mục [0] cho x trong các mục)'. – kennytm

+10

len (set (items)) == 1 chắc chắn là thành ngữ nhất. –

9

tôi ban đầu được giải thích bạn phải kiểm tra danh tính ("cùng một mục"), nhưng bạn đang thực sự thử nghiệm bình đẳng ("cùng giá trị"). (. Nếu bạn đang thử nghiệm bản sắc, sử dụng thay vì ==)

def all_same(items): 
    it = iter(items) 
    for first in it: 
    break 
    else: 
    return True # empty case, note all([]) == True 
    return all(x == first for x in it) 

Các công trình trên trên bất kỳ iterable, không chỉ liệt kê, nếu không bạn có thể sử dụng:

def all_same(L): 
    return all(x == L[0] for x in L) 

(Nhưng, IMHO, bạn cũng có thể sử dụng phiên bản-nó nói chung làm việc hoàn toàn tốt đẹp trên danh sách)

+0

+1 Tôi sẽ phải nhớ công thức đó. – aaronasterling

+0

@katrielalex: Sau đó, bạn phải thử/ngoại trừ StopIteration; tại thời điểm đó, đó là hành vi tương đương và cùng độ dài. –

+1

Tôi thích 'try: first = next (nó) ngoại trừ StopIteration: return True' - Tôi nghĩ rằng dòng chảy là rõ ràng hơn - nhưng sự khác biệt tương tự, thực sự. – katrielalex

4

này hoạt động cho cả chuỗi và iterables:.

def all_same(items): 
    it = iter(items) 
    first = next(it, None) 
    return all(x == first for x in it) 
+1

Ah, tôi đã tưởng tượng bạn sẽ kiểm tra 'đầu tiên là Không có' thay vì để cho sự sụp đổ này. Nó đưa ra kết quả đúng, nhưng tôi thích xử lý lỗi này/"trường hợp ngoại lệ" thay vì tùy thuộc vào mã sau để âm thầm làm điều đúng. –

+0

Tôi biết tôi rất không có ý kiến ​​trong quan điểm này, nhưng tôi không thích rằng một dòng khá đơn trở thành bốn vì tôi phải bắt một ngoại lệ (tôi nói chung, bạn đã sử dụng một/break trong bạn trả lời). Vâng, tôi biết về EAFP, nhưng vẫn còn, nếu tôi có thể tránh nó ... Cảm ơn cho 1, mặc dù :-) – tokland

0

Điều này có thể nhanh hơn nếu bạn biết các giá trị nằm trong danh sách.

def all_same(values): 
    return values.count(values[0]) == len(values) 
5

Cách tốt nhất để làm điều này là sử dụng Python sets.You cần phải xác định all_same như thế này:

def all_same(items): 
    return len(set(items)) == 1 

Test:

>>> def all_same(items): 
...  return len(set(items)) == 1 
... 
>>> 
>>> property_list = ["one", "one", "one"] 
>>> all_same(property_list) 
True 
>>> property_list = ["one", "one", "two"] 
>>> all_same(property_list) 
False 
>>> 
-1

Tôi tạo ra đoạn mã này cho cùng một vấn đề sau khi suy nghĩ. Tôi không chắc chắn nếu nó hoạt động cho mọi kịch bản mặc dù.

def all_same(list): 
    list[0]*len(list) == list 
+0

Tôi sợ điều này không làm việc cả. Ví dụ.'test_list = [1, 1]' và 'all_same (test_list)' trả về 'False' vì' test_list [0] = 1' và 'len (test_list) = 2' do đó kết quả chỉ là' 1 * 2 = 2' . Sau đó, bạn kiểm tra '2 == test_list', mà không phải là True. –

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