我如何知道我的列表是否全部为1?

时间:2012-11-28 19:37:42

标签: python

我正在寻找更好的方法,可能正在使用列表推导?

>>> 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
>>> 

8 个答案:

答案 0 :(得分:78)

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

这会将all函数与generator expression

一起使用

如果您在列表中始终只有零和一个(或者如果您只想检查列表中是否没有任何零),那么只需使用 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) solution在大多数情况下是最快的。如果你很少有所有的列表(数据是随机的,等等),或者你不想使用额外的RAM,我的解决方案会更好。如果列表很小,则差异可以忽略不计。

答案 1 :(得分:42)

更多可能的方法:

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]

答案 2 :(得分:16)

除了已提供的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

<强>买者; (和赎回因子):

  • 正如一些人所指出的那样,这种可读性较差;然而...
  • 我会留下这个:
    • 正如@ WinstonEwert的回答所示,该解决方案的性能优于@BlaXpirit提出的all()解决方案
    • 我认为StackOverflow的大多数成员都喜欢学习新东西;替代解决方案通过促进讨论,​​调查和分析为此做出了贡献。

答案 3 :(得分:10)

@ 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?不,empty product的值是1.这在数学上是最一致的(单击链接以获得完整的解释),因为1是乘法的identity element。 (记住sum([])返回0,即添加的标识元素。)

理解身份元素扮演的特殊角色,并回到原来的问题:

all([])

相当于使用Boolean and operator缩小列表。 and的标识元素为True,因此空列表的结果为True

any([])

or的标识元素为False,与此表达式的值相同。

答案 4 :(得分:2)

这将通过列表并收集任何非1的条款。如果存在这些条款,则bool返回True并且答案为False。

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

答案 5 :(得分:1)

使用all()的堂兄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

答案 6 :(得分:1)

怎么样:

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

答案 7 :(得分:1)

另一种方式是:

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