我如何知道我的列表是否全1?
我正在寻找更好的方法,可能是使用列表parsing?
>>> 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
使用了一个生成器expression式 。
如果你总是只有零和列表中的一个(或者如果你想检查列表是否没有任何零),那么只需使用all
没有任何额外的技巧:
>>> x = [1, 0, 1, 1, 1, 0] >>> all(x) False
一些解决scheme的基准 :
数字意味着运行一次解决scheme花费的毫秒数(运行1000次的平均值)
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
以下testing用例被使用:
[] # 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
意味着解决scheme给出了错误的答案 ; RE
代表运行时错误 。
所以我的判断是, Winston Ewert的x==[1]*len(x)
解决scheme在大多数情况下是最快的。 如果你很less有所有的列表(数据是随机的等),或者你不想使用额外的内存,我的解决scheme效果更好。 如果名单很小,差异可以忽略不计。
还有更多可能的方法:
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
警告; (和赎回因素) :
- 正如一些人指出的那样,这是不太可读的; 然而…
- 我会离开这一点,因为:
- 正如@ WinstonEwert的答案所示,这个解决scheme可以比@BlaXpirit提出的
all()
解决scheme更好地执行 - 我认为StackOverflow的大多数成员更喜欢学习新的东西; 通过促进讨论,询问和分析,替代解决scheme为此做出了贡献。
- 正如@ WinstonEwert的答案所示,这个解决scheme可以比@BlaXpirit提出的
@桑普森有一个好主意,可以使用一些帮助。 考虑投票他的答案,并把这看作是一个扩展的评论。 (我不知道如何使代码在评论中看起来不错)。 这是我的重写:
>>> 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倍)
更新:空洞的真相和减less空列表
彼得·奥尔森在评论中写道:
如果列表是空的,那么命题“列表的每个元素等于一个”是真实的 。
在评论中进一步讨论导致@桑普森写作:
我觉得应该是虚伪的, 也许这个post里的某个人最终会启发我们的语义。 – 桑普森
让我们看看Python认为:
>>> all([]) True
那么怎么样:
>>> any([]) False
那么为什么这是正确的? 如果你还没碰到过,可能会让人困惑。 有一种思考方式可以帮助你理解和记忆。
让我们稍微回顾一下,从下面开始:
>>> sum(mylist)
Python的内置函数sum
从左到右叠加一个迭代项并返回总和。 更加抽象地思考, sum
通过应用加法运算符来减less迭代次数。
>>> sum([]) 0
没有任何东西的总和是0.这相当直观。 但是这个怎么样:
>>> product([])
好的,它实际上返回一个名称错误,因为product
不作为内置函数存在。 但是,它应该返回什么? 0? 不, 空值的值是1.这是math上最一致的(单击链接以获得完整的解释),因为1是乘法的标识元素 。 (记住sum([])
返回0,用于添加的标识元素。)
了解身份要素所起的特殊作用,回到原来的问题:
all([])
相当于使用布尔and
运算符来减less列表。 和的标识元素为True,因此空列表的结果为True
。
any([])
or
的标识元素为False
,与此expression式的值相同。
这通过列表并收集任何不是1的条款。如果这些条款存在,那么bool返回True,答案是False。
not(bool(filter(lambda y: y!=1, x)))
一些使用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
这个怎么样 :
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