Если вы ищете решение для лицензирования, вы можете проверить API TrueLicense . Он основан на использовании асимметричных клавиш. Однако это не означает, что ваше приложение не может быть взломан. Каждое приложение может быть исправлено с достаточным усилием. Что действительно важно, поскольку Стю ответил , выяснив, насколько необходима сильная защита.
Общий метод:
def checkEqual1(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == rest for rest in iterator)
Однострочный:
def checkEqual2(iterator):
return len(set(iterator)) <= 1
Также однострочный:
def checkEqual3(lst):
return lst[1:] == lst[:-1]
Разница между 3 версии:
checkEqual2
содержимое должно быть хешируемым. checkEqual1
и checkEqual2
могут использовать любые итераторы, но checkEqual3
должны принимать последовательный вход, обычно конкретные контейнеры, такие как список или кортеж. checkEqual1
останавливается, как только обнаруживается разница. checkEqual1
содержит больше кода на Python, это меньше эффективен, когда многие из элементов равны в начале. checkEqual2
и checkEqual3
всегда выполняют операции копирования O (N), они будут занимать больше времени, если большая часть вашего ввода вернет False. checkEqual2
и checkEqual3
сложнее адаптировать сравнение с a == b
до a is b
. timeit
результат для Python 2.7 и (только s1, s4, s7, s9 должны возвращать True)
s1 = [1] * 5000
s2 = [1] * 4999 + [2]
s3 = [2] + [1]*4999
s4 = [set([9])] * 5000
s5 = [set([9])] * 4999 + [set([10])]
s6 = [set([10])] + [set([9])] * 4999
s7 = [1,1]
s8 = [1,2]
s9 = []
получаем
| checkEqual1 | checkEqual2 | checkEqual3 | checkEqualIvo | checkEqual6502 |
|-----|-------------|-------------|--------------|---------------|----------------|
| s1 | 1.19 msec | 348 usec | 183 usec | 51.6 usec | 121 usec |
| s2 | 1.17 msec | 376 usec | 185 usec | 50.9 usec | 118 usec |
| s3 | 4.17 usec | 348 usec | 120 usec | 264 usec | 61.3 usec |
| | | | | | |
| s4 | 1.73 msec | | 182 usec | 50.5 usec | 121 usec |
| s5 | 1.71 msec | | 181 usec | 50.6 usec | 125 usec |
| s6 | 4.29 usec | | 122 usec | 423 usec | 61.1 usec |
| | | | | | |
| s7 | 3.1 usec | 1.4 usec | 1.24 usec | 0.932 usec | 1.92 usec |
| s8 | 4.07 usec | 1.54 usec | 1.28 usec | 0.997 usec | 1.79 usec |
| s9 | 5.91 usec | 1.25 usec | 0.749 usec | 0.407 usec | 0.386 usec |
Примечание:
# http://stackoverflow.com/q/3844948/
def checkEqualIvo(lst):
return not lst or lst.count(lst[0]) == len(lst)
# http://stackoverflow.com/q/3844931/
def checkEqual6502(lst):
return not lst or [lst[0]]*len(lst) == lst
Это еще один вариант, более быстрый, чем len(set(x))==1
для длинных списков (используется короткое замыкание)
def constantList(x):
return x and [x[0]]*len(x) == x
Сложная сравнительная работа:
len(set(the_list)) == 1
Использование set
удаляет все повторяющиеся элементы.
lambda lst: reduce(lambda a,b:(b,b==a[0] and a[1]), lst, (lst[0], True))[1]
Следующее короткое замыкание:
all(itertools.imap(lambda i:yourlist[i]==yourlist[i+1], xrange(len(yourlist)-1)))
reduce(lambda a,b:a==b, [2,2,2])
yields False
... Я отредактировал его, но таким образом это не совсем
– berdario
27 March 2014 в 11:41
Вы можете преобразовать список в набор. У набора не может быть дубликатов. Поэтому, если все элементы в исходном списке идентичны, набор будет иметь только один элемент.
if len(sets.Set(input_list)) == 1
// input_list has all identical elements.
Убедитесь, что все элементы равны первому.
np.allclose(array, array[0])
def allTheSame(i):
j = itertools.groupby(i)
for k in j: break
for k in j: return False
return True
Работает в Python 2.4, который не имеет «все».
for k in j: break
эквивалентно next(j)
. Вы также могли бы сделать def allTheSame(x): return len(list(itertools.groupby(x))<2)
, если бы не заботились об эффективности.
– ninjagecko
23 April 2012 в 18:06
Решение быстрее, чем использование set (), которое работает с последовательностями (а не итерами), состоит в простом подсчете первого элемента. Это предполагает, что список не пуст (но это тривиально проверить и решить, какой результат должен быть в пустом списке)
x.count(x[0]) == len(x)
несколько простых эталонных тестов:
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*5000', number=10000)
1.4383411407470703
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*4999+[2]', number=10000)
1.4765670299530029
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*5000', number=10000)
0.26274609565734863
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*4999+[2]', number=10000)
0.25654196739196777
x.count(next(x)) == len(x)
, чтобы он работал для любого контейнера x? Ahh .. nm, просто увидел, что .count доступен только для последовательностей. Почему он не реализован для других встроенных контейнеров? Является ли подсчет внутри словаря менее значимым, чем внутри списка?
– max
5 October 2010 в 06:09
count
не реализован для iterables, а не почему len
недоступен для итераторов. Ответ, вероятно, в том, что это просто недосмотр. Но для нас это непоправимо, потому что по умолчанию .count()
для последовательностей очень медленный (чистый python). Причина, по которой ваше решение так быстро, заключается в том, что он полагается на C-реализованный count
, предоставленный list
. Поэтому я предполагаю, что какой-либо истребимый метод реализации count
в C будет полезен вашему подходу.
– max
12 March 2016 в 04:36
Это простой способ сделать это:
result = mylist and all(mylist[0] == elem for elem in mylist)
Это немного сложнее, оно навлекает служебные вызовы функций, но семантика более четко прописана:
def all_identical(seq):
if not seq:
# empty list is False.
return False
first = seq[0]
return all(first == elem for elem in seq)
for elem in mylist[1:]
. Сомнительно, что он значительно улучшает скорость, поскольку, как я полагаю, elem[0] is elem[0]
, переводчик, вероятно, может сделать это сравнение очень быстро.
– Brendan
5 January 2017 в 16:58
Если вам интересно что-то более читаемое (но, конечно, не так эффективно), вы можете попробовать:
def compare_lists(list1, list2):
if len(list1) != len(list2): # Weed out unequal length lists.
return False
for item in list1:
if item not in list2:
return False
return True
a_list_1 = ['apple', 'orange', 'grape', 'pear']
a_list_2 = ['pear', 'orange', 'grape', 'apple']
b_list_1 = ['apple', 'orange', 'grape', 'pear']
b_list_2 = ['apple', 'orange', 'banana', 'pear']
c_list_1 = ['apple', 'orange', 'grape']
c_list_2 = ['grape', 'orange']
print compare_lists(a_list_1, a_list_2) # Returns True
print compare_lists(b_list_1, b_list_2) # Returns False
print compare_lists(c_list_1, c_list_2) # Returns False
Преобразуйте список в набор, а затем найдите количество элементов в наборе. Если результат равен 1, он имеет одинаковые элементы, а если нет, то элементы в списке не идентичны.
list1 = [1,1,1]
len(set(list1))
>1
list1 = [1,2,3]
len(set(list1)
>3
Измените список на набор. Тогда, если размер набора равен только 1, они должны быть одинаковыми.
if len(set(my_list)) == 1:
Сомневаюсь, что это «самый Pythonic», но что-то вроде:
>>> falseList = [1,2,3,4]
>>> trueList = [1, 1, 1]
>>>
>>> def testList(list):
... for item in list[1:]:
... if item != list[0]:
... return False
... return True
...
>>> testList(falseList)
False
>>> testList(trueList)
True
выполнит трюк.
for
можно сделать более Pythonic в if any(item != list[0] for item in list[1:]): return False
с точно такой же семантикой.
– musiphil
18 August 2016 в 20:59
Относительно использования reduce()
с lambda
. Вот рабочий код, который, как мне кажется, лучше, чем некоторые другие ответы.
reduce(lambda x, y: (x[1]==y, y), [2, 2, 2], (True, 2))
Возвращает кортеж, где первое значение является логическим, если все элементы одинаковы или нет.
Для чего это стоит, это появилось недавно в списке рассылки python-идей . Оказалось, что для этого уже существует рецепт itertools : 1
def all_equal(iterable):
"Returns True if all the elements are equal to each other"
g = groupby(iterable)
return next(g, True) and not next(g, False)
Предположительно, он работает очень хорошо и имеет несколько приятных свойств.
1Иными словами, я не могу взять кредит на то, чтобы придумать решение - и не может Я признаю, что даже нашел это.
Самый простой и элегантный способ заключается в следующем:
all(x==myList[0] for x in myList)
(Да, это даже работает с нулевым списком! Это потому, что это один из немногих случаев, когда python имеет ленивую семантику. )
Что касается производительности, это произойдет как можно скорее, поэтому оно асимптотически оптимально.
checkEqual1
. Я не знаю, почему.
– max
24 April 2012 в 18:20
first=myList[0]
all(x==first for x in myList)
, возможно
– ninjagecko
17 November 2015 в 13:48
first=myList[0]
будет вызывать IndexError
в пустом списке, поэтому комментаторы, которые говорили об этой оптимизации, о которой я упоминал, будут иметь дело с краем случайного списка. Однако оригинал прекрасен (x==myList[0]
в пределах all
, потому что он никогда не оценивается, если список пуст).
– ninjagecko
13 January 2016 в 11:45
Вы можете сделать:
reduce(and_, (x==yourList[0] for x in yourList), True)
Довольно раздражает, что python заставляет вас импортировать такие операторы, как operator.and_
. Начиная с python3, вам также нужно будет импортировать functools.reduce
.
(Вы не должны использовать этот метод, потому что он не сломается, если он найдет не равные значения, но продолжит изучение всего списка. просто включается здесь в качестве ответа для полноты.)
>>> a = [1, 2, 3, 4, 5, 6]
>>> z = [(a[x], a[x+1]) for x in range(0, len(a)-1)]
>>> z
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
# Replacing it with the test
>>> z = [(a[x] == a[x+1]) for x in range(0, len(a)-1)]
>>> z
[False, False, False, False, False]
>>> if False in z : Print "All elements are not equal"
Я бы сделал:
not any((x[i] != x[i+1] for i in range(0, len(x)-1)))
as any
перестает искать итерацию, как только обнаруживает условие True
.
all()
, почему бы не использовать all(x == seq[0] for x in seq)
? выглядит более pythonic и должен выполнять то же самое
– Chen A.
4 September 2017 в 07:36
. При преобразовании списка в набор удаляются повторяющиеся элементы. Поэтому, если длина преобразованного набора равна 1, это означает, что все элементы одинаковы.
len(set(input_list))==1
Вот пример
>>> a = ['not', 'the', 'same']
>>> b = ['same', 'same', 'same']
>>> len(set(a))==1 # == 3
False
>>> len(set(b))==1 # == 1
True
Это будет сравнивать (эквивалентность) первый элемент списка ввода со всеми остальными элементами в списке. Если все эквиваленты True будут возвращены, в противном случае возвращается False.
all(element==input_list[0] for element in input_list)
Вот пример
>>> a = [1, 2, 3, 4, 5]
>>> b = [1, 1, 1, 1, 1]
>>> all(number==a[0] for number in a)
False
>>> all(number==b[0] for number in b)
True
PS Если вы проверяете, соответствует ли весь список определенному значение, вы можете suibstitue значение in для input_list [0].
Можно использовать карту и лямбда
lst = [1,1,1,1,1,1,1,1,1]
print all(map(lambda x: x == lst[0], lst[1:]))
obj.__eq__
, когдаlhs is rhs
, и оптимизацию вне порядка, чтобы быстрее отсортировать отсортированные списки. – Glenn Maynard 2 October 2010 в 09:31[2,3,3,3]
? checkEqual3 правильно возвращает False. – kennytm 2 May 2016 в 11:25