我正在寻找更好的方法,可能是使用列表推导?
>>> 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
>>>
我正在寻找更好的方法,可能是使用列表推导?
>>> 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
>>>
>>> x = [1, 1, 1, 1, 1, 1]
>>> all(el==1 for el in x)
True
如果列表中总是只有零和一个(或者如果您只想检查列表是否没有任何零),那么只需使用all
没有任何额外的技巧:
>>> x = [1, 0, 1, 1, 1, 0]
>>> all(x)
False
一些解决方案的基准:
数字表示运行一次解决方案所需的时间(以毫秒为单位) (平均 1000timeit
次运行)
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)
解决方案在大多数情况下是最快的。如果您很少有所有列表(数据是随机的等),或者您不想使用额外的 RAM,我的解决方案效果更好。如果列表很小,则差异可以忽略不计。
还有更多可能的方法:
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]
除了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
警告; (和兑换因素):
all()
@BlaXpirit 提出的解决方案@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 在评论中写道:
如果列表为空,则命题“列表的每个元素都等于一个”是空虚的。
评论中的进一步讨论导致@sampson-chen 写作:
我觉得它应该是空洞的错误;也许这篇文章中的某个人最终会在语义上启发我们。– 桑普森陈
让我们看看 Python 是怎么想的:
>>> all([])
True
那么怎么样:
>>> any([])
False
那为什么是对的呢?如果您之前没有遇到过这种情况,可能会感到困惑。有一种思考方式可以帮助你理解和记忆。
让我们稍微备份一下,然后开始:
>>> sum(mylist)
Python 的内置函数sum
从左到右对可迭代的项求和并返回总数。更抽象地思考,sum
通过应用加法运算符来减少迭代。
>>> sum([])
0
什么都没有的总和是 0。这很直观。但是这个呢:
>>> product([])
好的,它实际上返回了一个名称错误,因为product
它不作为内置函数存在。但它应该返回什么?0? 不,空乘积的值是 1。这在数学上是最一致的(单击链接查看完整说明),因为 1 是乘法的单位元。(记住sum([])
返回 0,加法的标识元素。)
以此理解恒等元素所起的特殊作用,回到原来的问题:
all([])
相当于使用布尔and
运算符减少列表。的标识元素为and
True,因此空列表的结果为True
。
any([])
的标识元素or
是False
,与此表达式的值相同。
这将遍历列表并收集任何不是 1 的术语。如果这些术语存在,则 bool 返回 True,答案为 False。
not(bool(filter(lambda y: y!=1, x)))
一些使用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
这个怎么样 :
lo = min(L)
hi = max(L)
if (lo != 1) and (hi != 1) and (lo != hi):
print "fail"
还有一种方法是:
arr = [1,1,1,1]
len(arr) == sum(arr) #True if arr is all 1's