Мне нужна функция, которая принимает list и выводитTrue, если все элементы во входном списке оцениваются как равные друг другу с использованием стандартного оператора равенства и False в противном случае.
Я чувствую, что было бы лучше выполнить итерацию по списку, сравнивая соседние элементы, а затем AND все результирующие логические значения. Но я не уверен, какой наиболее питонический способ сделать это.
defall_equal_6502(lst): returnnot lst or [lst[0]]*len(lst) == lst
Но у них есть некоторые недостатки, а именно:
all_equal и all_equal2 могут использовать любые итераторы, но остальные должны принимать ввод последовательности, обычно это конкретные контейнеры, такие как список или кортеж.
all_equal и all_equal3 остановитесь, как только будет найдено различие (то, что называется "короткое замыкание"), тогда как все альтернативы требуют повторения всего списка, даже если вы можете сказать, что ответ есть, False просто взглянув на первые два элемента.
В all_equal2 содержимое должно быть хэшируемым. Например, список списков вызовет TypeError.
all_equal2 (в худшем случае) и all_equal_6502 создайте копию списка, что означает, что вам нужно использовать вдвое больше памяти.
В Python 3.9, используя perfplot, мы получаем эти тайминги (чем меньше Runtime [s], тем лучше):
Ответ 2
Решение, более быстрое, чем использование set(), которое работает с последовательностями (не повторяющимися), - это просто посчитать первый элемент. Предполагается, что список непустой (но это тривиально проверить, и решите сами, каким должен быть результат в пустом списке)
[редактировать: этот ответ касается текущего ответа, набравшего наибольшее количество голосов itertools.groupby (что является хорошим ответом), позже.]
Без перезаписи программы наиболее асимптотически производительный и наиболее читаемый способ заключается в следующем:
all(x==myList[0] for x in myList)
(Да, это работает даже с пустым списком! Это потому, что это один из немногих случаев, когда python имеет ленивую семантику.)
Это приведет к сбою в кратчайшие возможные сроки, поэтому это асимптотически оптимально (ожидаемое время составляет приблизительно O (# uniques), а не O (N), но в худшем случае время все равно O (N)). Предполагается, что вы раньше не видели эти данные...
(Если вы заботитесь о производительности, но не настолько сильно о производительности, вы можете просто сначала выполнить обычные стандартные оптимизации, такие как удаление константы myList[0] из цикла и добавление неуклюжей логики для крайнего случая, хотя это то, что компилятор python может в конечном итоге научиться делать, и поэтому не следует этого делать без крайней необходимости, поскольку это ухудшает читаемость при минимальном выигрыше.)
Если вы немного больше заботитесь о производительности, это в два раза быстрее, чем указано выше, но немного более подробно:
for x in iterator: if x!=firstItem: returnFalse returnTrue
Если вы еще больше заботитесь о производительности (но не настолько, чтобы переписывать свою программу), используйте набравший наибольшее количество голосов itertools.groupby ответ, который в два раза быстрее, чем allEqual потому что он, вероятно, оптимизирован для кода C. (Согласно документам, это не должно (аналогично этому ответу) иметь каких-либо накладных расходов на память, потому что отложенный генератор никогда не преобразуется в список ... о чем можно беспокоиться, но псевдокод показывает, что сгруппированные "списки" на самом деле являются отложенными генераторами.)
Если вас еще больше волнует производительность, читайте дальше...
примечания относительно производительности, потому что в других ответах говорится об этом по какой-то неизвестной причине:
... если вы видели данные раньше и, вероятно, используете какую-то структуру данных коллекции, и вас действительно волнует производительность, вы можете получить .isAllEqual() бесплатно O(1), дополнив свою структуру Counter, Которая обновляется при каждой операции вставки / удаления / и т.д. И просто проверяя, имеет ли она вид {something:someCount} т.Е. len(counter.keys())==1; в качестве альтернативы вы можете сохранить счетчик сбоку в отдельной переменной. Это доказуемо лучше, чем что-либо еще с точностью до constant factor. Возможно, вы также можете использовать FFI в python с ctypes выбранным вами методом и, возможно, с эвристикой (например, если это последовательность с getitem , затем проверяйте первый элемент, последний элемент, затем элементы по порядку).
Конечно, есть кое-что, что нужно сказать для удобства чтения.