How do I know if my list has all 1s?

Question:

I am looking for a better way, may be using list comprehensions?

>>> 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
>>> 
Asked By: daydreamer

||

Answers:

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

This uses the function all with a generator expression.


If you always have only zeroes and ones in the list (or if you want to just check if the list doesn’t have any zeroes), then just use all without any additional tricks:

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

Benchmark of some solutions:
The numbers mean what time in milliseconds it took to run the solution once (average of 1000 timeit runs)

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  

The following test cases were used:

[] # 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 means that the solution gave a wrong answer; RE stands for runtime error.


So my verdict is, Winston Ewert‘s x==[1]*len(x) solution is the fastest in most cases. If you rarely have lists of all ones (the data is random, etc.) or you don’t want to use additional RAM, my solution works better. If the lists are small, the difference is negligible.

Answered By: Oleh Prypin

Some console examples using all()‘s 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
Answered By: Ashwini Chaudhary

In addition to the all() answer already provided, you can also do it with 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; (and Redeeming Factor):

  • As some have pointed out, this is less readable; however…
  • I’ll leave this up since:
    • As the results in @WinstonEwert’s answer demonstrate, this solution can perform better than the all() solution proposed by @BlaXpirit
    • I think most members of StackOverflow prefer to learn new things; alternative solutions contribute to that end by prompting discussion, inquiry, and analysis.
Answered By: sampson-chen

This goes through the list and collects any terms that aren’t 1. If those terms exist, then bool returns True and the answer is False.

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

@sampson-chen had a good idea that could use some help. Consider up voting his answer and look at this this as an extended comment. (I don’t know how to make code look good in a comment). Here’s my rewrite:

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

This code does not exactly match the original question because it returns False for an empty list which could be good or bad but probably doesn’t matter.

Edit

Based on community feedback (thanks @Nabb), here is a second rewrite:

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

This properly handles the case where x is an empty list.

I think this is readable. And the variant part is faster as written (almost twice as fast). In fact, on my Python 2.7 system, it’s always faster for lists up to 20 elements and for lists that are all 1’s. (Up to 3 times faster.)

Update: Vacuous Truth and Reduction of an Empty List

@Peter Olson wrote in a comment:

If the list is empty, then proposition “every element of the list equals one” is vacuously true.

Further discussion in the comments lead up to @sampson-chen writing:

I felt that it ought to be vacuously false; maybe someone in this post will eventually enlighten us on the semantics. – sampson-chen

Let’s see what Python thinks:

>>> all([])
True

Well then how about:

>>> any([])
False

So why is that right? If you haven’t run into this before it might be confusing. There’s a way to think about that may help you understand and remember.

Let’s back up a little bit and start with:

>>> sum(mylist)

Python’s built-in function sum sums items of an iterable from left to right and returns the total. Thinking more abstractly, sum reduces an iterable by applying the addition operator.

>>> sum([])
0

The sum of nothing is 0. That’s fairly intuitive. But what about this:

>>> product([])

Okay, it actually returns a name error because product doesn’t exist as a built-in function. But what should it return? 0? No, the value of an empty product is 1. That’s most mathematically consistent (click the link for a full explanation), because 1 is the identity element for multiplication. (Remember sum([]) returned 0, the identity element for addition.)

Taking this understanding of the special role the identity element plays, and returning to the original problem:

all([])

Is equivalent to reducing the list using the Boolean and operator. The identity element for and is True, so the result for the empty list is True.

any([])

The identity element for or is False, the same as the value of this expression.

Answered By: jimhark

Yet more possible methods:

x == [1] * len(x)

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

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

Some timing results:

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]

And on PyPy because: why not?

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]
Answered By: Winston Ewert

how about this :

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

Yet another way is:

arr = [1,1,1,1]
len(arr) == sum(arr) #True if arr is all 1's
Answered By: Adam
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.