Подтвердить что ты не робот

Как узнать, имеет ли мой список все 1s?

Я ищу лучший способ, может быть, использование списков?

>>> x = [1, 1, 1, 1, 1, 1]
>>> x
[1, 1, 1, 1, 1, 1]
>>> for i in x:
...   if i!=1:
...     print "fail"
... 
>>> 
>>> x = [1, 1, 1, 1, 1, 0]
>>> for i in x:
...   if i!=1:
...     print "fail"
... 
fail
>>> 
4b9b3361

Ответ 1

>>> x = [1, 1, 1, 1, 1, 1]
>>> all(el==1 for el in x)
True

Здесь используется функция all с выражение генератора.


Если у вас всегда есть только нули и единицы в списке (или если вы хотите просто проверить, нет ли в списке нулей), просто используйте all без каких-либо дополнительных трюков

>>> x = [1, 0, 1, 1, 1, 0]
>>> all(x)
False

Контрольный показатель некоторых решений:
Цифры означают, какое время в миллисекундах потребовалось для запуска решения один раз (в среднем 1000 timeit работает)

Python 3.2.3

              all(el==1 for el in x): 0.0003 0.0008 0.7903 0.0804 0.0005 0.0006
                       x==[1]*len(x): 0.0002 0.0003 0.0714 0.0086 0.0045 0.0554
         not([1 for y in x if y!=1]): 0.0003 0.0005 0.4142 0.1117 0.1100 1.1630
                set(x).issubset({1}): 0.0003 0.0005 0.2039 0.0409 0.0476 0.5310
y = set(x); len(y)==1 and y.pop()==1:   WA   0.0006 0.2043 0.0517 0.0409 0.4170
                   max(x)==1==min(x):   RE   0.0006 0.4574 0.0460 0.0917 0.5466
                 tuple(set(x))==(1,):   WA   0.0006 0.2046 0.0410 0.0408 0.4238
not(bool(filter(lambda y: y!=1, x))):   WA     WA     WA   0.0004 0.0004 0.0004
                              all(x): 0.0001 0.0001 0.0839   WA   0.0001   WA  

Python 2.7.3

              all(el==1 for el in x): 0.0003 0.0008 0.7175 0.0751 0.0006 0.0006
                       x==[1]*len(x): 0.0002 0.0003 0.0741 0.0110 0.0094 0.1015
         not([1 for y in x if y!=1]): 0.0001 0.0003 0.3908 0.0948 0.0954 0.9840
                set(x).issubset({1}): 0.0003 0.0005 0.2084 0.0422 0.0420 0.4198
y = set(x); len(y)==1 and y.pop()==1:   WA   0.0006 0.2083 0.0421 0.0418 0.4178
                   max(x)==1==min(x):   RE   0.0006 0.4568 0.0442 0.0866 0.4937
                 tuple(set(x))==(1,):   WA   0.0006 0.2086 0.0424 0.0421 0.4202
not(bool(filter(lambda y: y!=1, x))): 0.0004 0.0011 0.9809 0.1936 0.1925 2.0007
                              all(x): 0.0001 0.0001 0.0811   WA   0.0001   WA  

[PyPy 1.9.0] Python 2.7.2

              all(el==1 for el in x): 0.0013 0.0093 0.4148 0.0508 0.0036 0.0038
                       x==[1]*len(x): 0.0006 0.0009 0.4557 0.0575 0.0177 0.1368
         not([1 for y in x if y!=1]): 0.0009 0.0015 175.10 7.0742 6.4390 714.15 # No, this wasn't run 1000 times. Had to time it separately.
                set(x).issubset({1}): 0.0010 0.0020 0.0657 0.0138 0.0139 0.1303
y = set(x); len(y)==1 and y.pop()==1:   WA   0.0011 0.0651 0.0137 0.0137 0.1296
                   max(x)==1==min(x):   RE   0.0011 0.5892 0.0615 0.1171 0.5994
                 tuple(set(x))==(1,):   WA   0.0014 0.0656 0.0163 0.0142 0.1302
not(bool(filter(lambda y: y!=1, x))): 0.0030 0.0081 0.2171 0.0689 0.0680 0.7599
                              all(x): 0.0011 0.0044 0.0230   WA   0.0013   WA  

Использовались следующие тестовые примеры:

[] # True
[1]*6 # True
[1]*10000 # True
[1]*1000+[2]*1000 # False
[0]*1000+[1]*1000 # False
[random.randint(1, 2) for _ in range(20000)] # False

WA означает, что решение дало неправильный ответ; RE означает ошибку времени выполнения.


Итак, мой вердикт, решение Winston Ewert x==[1]*len(x) является самым быстрым в большинстве случаев. Если у вас редко есть списки всех (данные случайные и т.д.), Или вы не хотите использовать дополнительную оперативную память, мое решение работает лучше. Если списки малы, разница незначительна.

Ответ 2

Еще более возможные методы:

x == [1] * len(x)

list(set(x)) == [1]

tuple(set(x)) == (1,)

Некоторые результаты синхронизации:

all(el==1 for el in x)                   [1.184262990951538, 1.1856739521026611, 1.1883699893951416]
y = set(x);len(y) == 1 and y.pop() == 1  [0.6140780448913574, 0.6152529716491699, 0.6156158447265625]
set(x) == set([1])                       [0.8093318939208984, 0.8106880187988281, 0.809283971786499]
not(bool(filter(lambda y: y!=1, x)))     [1.615243911743164, 1.621769905090332, 1.6134231090545654]
not any(i!=1 for i in x)                 [1.1321749687194824, 1.1325697898864746, 1.132157802581787]
x == [1]*len(x)                          [0.3790302276611328, 0.3765430450439453, 0.3812289237976074]
list(set(x)) == [1]                      [0.9047720432281494, 0.9006211757659912, 0.9024860858917236]
tuple(set(x)) == (1,)                    [0.6586658954620361, 0.6594271659851074, 0.6585478782653809]

И на PyPy, потому что: почему бы и нет?

all(el==1 for el in x)                   [0.40866899490356445, 0.5661730766296387, 0.45672082901000977]
y = set(x);len(y) == 1 and y.pop() == 1  [0.6929471492767334, 0.6925959587097168, 0.6805419921875]
set(x) == set([1])                       [0.956063985824585, 0.9526000022888184, 0.955935001373291]
not(bool(filter(lambda y: y!=1, x)))     [0.21160888671875, 0.1965351104736328, 0.19921493530273438]
not any(i!=1 for i in x)                 [0.44970107078552246, 0.509315013885498, 0.4380669593811035]
x == [1]*len(x)                          [0.5422029495239258, 0.5407819747924805, 0.5440030097961426]
list(set(x)) == [1]                      [1.0170629024505615, 0.9520189762115479, 0.940842866897583]
tuple(set(x)) == (1,)                    [0.9174900054931641, 0.9112720489501953, 0.9102160930633545]

Ответ 3

В дополнение к уже предоставленному ответу all() вы также можете сделать это с помощью set():

>>> x = [1, 1, 1, 1, 1, 1]
>>> y = set(x)
>>> len(y) == 1 and y.pop() == 1
True

>>> a = [1, 1, 1, 1, 0]
>>> b = set(a)
>>> len(b) == 1 and b.pop() == 1
False

Caveat; (и коэффициент выкупа):

  • Как указывали некоторые, это менее читаемо; Однако...
  • Я оставлю это с тех пор:
    • Как показывают результаты в ответе @WinstonEwert, это решение может работать лучше, чем решение all(), предложенное @BlaXpirit
    • Я думаю, что большинство членов StackOverflow предпочитают изучать новые вещи; альтернативные решения способствуют достижению этой цели, предлагая обсуждение, запрос и анализ.

Ответ 4

@sampson-chen имел хорошую идею, которая могла бы помочь. Подумайте о своем голосовании и посмотрите на это как на расширенный комментарий. (Я не знаю, как сделать код хорошо выглядеть в комментарии). Здесь я переписываю:

>>> setone = set([1])
>>> x = [1, 1, 1, 1, 1, 1]
>>> set(x) == setone
True

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

Изменить

Основываясь на отзывах сообщества (спасибо @Nabb), вот второе переписывание:

>>> x = [1, 1, 1, 1, 1, 1]
>>> set(x).issubset({1})

Это правильно обрабатывает случай, когда x - пустой список.

Я думаю, что это читаемо. А вариантная часть быстрее, чем написано (почти в два раза быстрее). Фактически, на моей системе Python 2.7 она всегда быстрее для списков до 20 элементов и для списков, которые являются всеми 1. (До 3 раз быстрее.)

Обновление: свободная истина и уменьшение пустого списка

@Peter Olson написал в комментарии:

Если список пуст, то предложение "каждый элемент списка равно одному" vacuously true.

Дальнейшее обсуждение в комментариях приводит к написанию @sampson-chen:

Я чувствовал, что это должно быть откровенно ложным; возможно, кто-то в этом посте, в конце концов, просветит нас по семантике. - sampson-chen

Посмотрите, что думает Python:

>>> all([])
True

Ну, а как насчет:

>>> any([])
False

Так почему же так? Если вы не столкнулись с этим, прежде чем это может сбить с толку. Там можно подумать о том, что может помочь вам понять и запомнить.

Вернемся немного назад и начинаем с:

>>> sum(mylist)

Встроенная функция Python sum суммирует элементы итерации слева направо и возвращает итоговое значение. Думая более абстрактно, sum уменьшает итерабельность, применяя оператор сложения.

>>> sum([])
0

Сумма ничего не равна 0. Это довольно интуитивно понятно. Но как насчет этого:

>>> product([])

Хорошо, он фактически возвращает ошибку имени, потому что product не существует как встроенная функция. Но что он должен вернуть? 0? Нет, значение пустого продукта равно 1. Это наиболее математически согласованное (щелкните ссылку для полного объяснения), потому что 1 является элемент идентификации для умножения. (Помните sum([]), возвращенный 0, элемент идентификации для сложения.)

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

all([])

Это эквивалентно сокращению списка с помощью Boolean and operator. Элемент идентификации для and равен True, поэтому для пустого списка будет True.

any([])

Элемент идентификации для or равен False, то же самое, что и значение этого выражения.

Ответ 5

Это проходит через список и собирает любые термины, которые не являются 1. Если эти термины существуют, то bool возвращает True, а ответ - False.

not(bool(filter(lambda y: y!=1, x)))

Ответ 6

Некоторые примеры консолей с помощью all() cousin any():

In [4]: x = [1, 1, 1, 1, 1, 1]

In [5]: not any(i!=1 for i in x)
Out[5]: True

In [6]: x = [1, 1, 1, 1, 1, 0]
In [7]: not any(i!=1 for i in x)
Out[7]: False

Ответ 7

как насчет этого:

lo = min(L)
hi = max(L)
if (lo != 1) and (hi != 1) and (lo != hi):
   print "fail"

Ответ 8

Еще один способ:

arr = [1,1,1,1]
len(arr) == sum(arr) #True if arr is all 1's