Python: определить, все ли элементы списка являются одинаковыми [дубликаты]

На этот вопрос уже есть ответ здесь:

проверить, все ли элементы в списке идентичны 24 ответа

В некотором моем коде я помещаю ряд объектов в список и строю дополнительный список из их атрибутов, который является строкой. Мне нужно определить, все ли элементы в этом втором списке имеют одно и то же значение, не зная заранее, какое это значение, и вернуть логическое значение, чтобы я мог делать разные вещи в своем коде в зависимости от результата.

Я не могу знать названия свойств заранее, поэтому я пытаюсь сделать что-то как можно более общее.

Чтобы проиллюстрировать пример, идеальная функция с именем "all_same" будет работать так:

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

Я думал о том, чтобы составить список уникальных элементов, а затем проверить, равна ли его длина 1, но я не уверен, что это самое элегантное решение.

 wheaties31 авг. 2016 г., 04:14
Хех, первый вопрос, который я видел, где предыдущий вопрос - дубликат. Время иногда работает наоборот.
 max03 окт. 2010 г., 20:00
Просто понял, что я задал такой же вопрос здесь:stackoverflow.com/questions/3844801/..., Как связать эти два вопроса?
 Nick T20 июн. 2019 г., 19:29
Название этого звучит так, будто спрашивающий хочет проверитьидентичность (a is b) неравенство (a == b)

Ответы на вопрос(7)

Я создал этот фрагмент кода для той же самой проблемы после обдумывания. Я не совсем уверен, работает ли он для каждого сценария, хотя.

def all_same(list):
    list[0]*len(list) == list
 n1k31t407 нояб. 2017 г., 07:20
Боюсь, это не работает вообще. Например.test_list=[1, 1] а такжеall_same(test_list) возвращаетсяFalse так какtest_list[0] = 1 а такжеlen(test_list) = 2 так что результаты просто1 * 2 = 2, Тогда вы тестируете2 == test_list, что не соответствует действительности.

Это может быть быстрее, если вы знаете, значения находятся в списке.

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

def all_same(items):
  it = iter(items)
  first = next(it, None)
  return all(x == first for x in it)
 tokland24 сент. 2010 г., 18:31
Я знаю, что в этом мнении я очень не в духе, но мне не нравится, что довольно одиночная строка превращается в четыре, потому что я должен поймать исключение (я говорю в общем, вы использовали ответ for / break в своем ответе). Да, я знаю о EAFP, но все же, если я могу избежать этого ... Спасибо за +1, хотя :-)
 Roger Pate24 сент. 2010 г., 18:21
Ах, я представлял, что вы проверитеfirst is None вместо того, чтобы позволить этому провалиться. Это дает правильный результат, но я предпочитаю трактовать это как ошибку / «исключительное обстоятельство», а не полагаться на последующий код, который молча делает правильные вещи.
Решение Вопроса
def all_same(items):
    return all(x == items[0] for x in items)

Пример:

>>> 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
 Einar24 сент. 2010 г., 16:23
Очень хорошо, я воспользуюсь этим, спасибо!
 JulienD19 мая 2015 г., 11:24
len(set(items)) == 1 быстрее.
 salparadise22 июл. 2017 г., 09:02
@ E-удовлетворительный улучшить ответ с этой версией.
 FogleBird03 февр. 2016 г., 17:50
@muraveill Это будет зависеть от входа.
 e-satis06 мар. 2016 г., 19:11
Этот ответ имеет несколько недостатков: он работает только с индексируемыми и с равенством (и без идентичности). Отсюда немного улучшенная версия: оператор импорта def same (итерируемый, сравнить = operator.eq, value_on_empty = True): gen = iter (итерируемый) start = next (gen, value_on_empty) вернуть все (сравнить (start, x) для x в gen) Это будет работать с итерациями без размера, такими как генераторы, позволяя вам указать, что означает «то же самое» и что делать с пустым значением.

Изначально я интерпретировал, что вы тестируете личность («тот же предмет»), но вы действительно тестируетеравенство («то же значение»). (Если вы проверяли личность, используйтеявляется вместо ==.)

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)

Вышеописанное работает с любыми повторяемыми, а не только со списками, в противном случае вы можете использовать:

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

(Но, IMHO, вы могли бы также использовать общую версию - она ​​отлично работает в списках.)

 Roger Pate24 сент. 2010 г., 17:14
@tokland: не работает, что делать, если вы хотите пройти[None, 42] к функции? (Вы можете использовать объект-страж, который когда-либо использовался только в этой функции, но это намного сложнее, чем здесь стоит.)
 Katriel24 сент. 2010 г., 16:49
я предпочитаюtry: first = next(it) except StopIteration: return True - Я думаю, что поток яснее - но та же разница, на самом деле.
 Roger Pate24 сент. 2010 г., 18:28
(ответ в комментарииэтот ответВыложил, прежде чем спросил! :П)
 aaronasterling24 сент. 2010 г., 16:30
+1 Мне придется запомнить этот рецепт.
 tokland24 сент. 2010 г., 18:22
@ Роджер: Вот мой ответ, я думаю, что вы узнаете последнее утверждение ;-) Вы правы, что обычно стражи не могут быть потенциальным элементом во входных данных, но здесь это неприменимо. Или я что-то упустил?
 Roger Pate24 сент. 2010 г., 18:08
@tokland: я знаю, что часовой никогда не используется, поэтому я поставил None на первое место: вы не можете определить, является ли None, который вы получаете, из списка или из второго параметра. Не могли бы вы опубликовать код? (Новый ответ? Так как это также ответило бы на этот вопрос.) Очевидно, мы воображаем разные вещи.
 tokland24 сент. 2010 г., 18:06
@ Роджер: если вы пройдете [Нет, 42], вы получите False, как и следовало ожидать. Обратите внимание, что страж никогда не используется, если итерация пуста.
 tokland24 сент. 2010 г., 17:00
Мне нравится это решение. Даже если ОП запрашивает только списки, генераторы теперь настолько распространены в Python, что лучше не предполагать, что ввод является последовательностью. Обратите внимание, что вы можете немного упростить это с помощью Python> = 2.6: first = next (it, None)
 Roger Pate24 сент. 2010 г., 16:48
@katrielalex: Тогда вы должны попробовать / кроме StopIteration; в этот момент это эквивалентное поведение и одинаковая длина.
 Katriel24 сент. 2010 г., 16:50
@ Роджер: извините, заметил это и удалил слишком поздно. В самом деле! знак равно

Лучший способ сделать это - использовать наборы Python. Вам нужно определитьall_same как это:

def all_same(items):
    return len(set(items)) < 2

Тестовое задание:

>>> def all_same(items):
...     return len(set(items)) < 2
... 
>>> 
>>> property_list = ["one", "one", "one"]
>>> all_same(property_list)
True
>>> property_list = ["one", "one", "two"]
>>> all_same(property_list)
False
>>> property_list = []
>>> all_same(property_list)
True
 Trevor Hickey23 мая 2019 г., 17:53
Это не сработало для меня, так как элементы моего списка являются словарями и не могут быть хешированы

Вы могли бы обмануть и использоватьset:

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

или вы можете использовать:

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

или если вы имеете дело с итерируемым вместо списка:

def all_same( iterable ):
    it_copy = tee( iterable, 1 )
    return len( set( it_copy) ) == 1
 jw01313 янв. 2016 г., 02:46
@muraveill Какую машину вы использовали и можете ли вы воспроизвести эти результаты? На обеих машинах я получаю противоположное относительное упорядочение:all() подход примерно в 3 раза быстрее, чемset() подход.
 Beni Cherniavsky-Paskin24 сент. 2010 г., 17:05
len (set (items)) == 1 определенно самый идиоматичный.
 FogleBird24 сент. 2010 г., 16:18
В наборе будет только один элемент, в списке будет N.
 kennytm24 сент. 2010 г., 16:21
Вы можете использовать выражение генератора во втором коде.all(x == items[0] for x in items).
 JulienD19 мая 2015 г., 11:22
Это также намного быстрее:a = ["a"]*100; a[53]="b". %timeit len(set(a)) == 1 -> 2.83us за цикл.%timeit all(x==a[0] for x in a) -> 7,78us за цикл.
 JulienD13 янв. 2016 г., 09:01
Это был старый MacBook Air. Я сделал это снова на MacBook Pro:len(set(a)): 1,81 мкс на петлю,all(x==a[0] for x in a): 5,26 мкс на петлю.

Ваш ответ на вопрос