检查列表中的所有元素是否相同 [英] check if all elements in a list are identical
问题描述
我需要以下函数:
输入:a 列表
p>
输出:
-
True
如果输入列表中的所有元素使用标准等式运算符计算为彼此相等;
效果:当然,我不希望产生任何不必要的开销。
我觉得最好:
- 遍历列表
- 比较相邻元素
- 和
AND
所有生成的布尔值
但我不知道什么是最坏的方式
EDIT
感谢所有伟大的答案。我给了几个评分,很难在@KennyTM和@Ivo van der Wijk解决方案之间选择。
缺少短路功能只会伤害长输入(超过〜50个元素),早期具有不等的元素。如果这种情况经常发生(多长时间取决于列表可能有多长时间),则需要短路。最好的短路算法似乎是@KennyTM checkEqual1
。但是,这样做的成本很高:
- 性能几乎相同的列表中达到20倍
- 短名单上效果最高可达2.5倍
如果具有早期不相等元素的长输入未发生足够少),不需要短路。然后,到目前为止,最快的是@Ivo van der Wijk解决方案。
一般方法:
def checkEqual1(iterator):
iterator = iter(iterator)
try:
first = next $ b except StopIteration:
return True
return all(first == rest for rest in iterator)
b $ b
一行:
def checkEqual2(iterator):
return len ))<= 1
还有一行:
def checkEqual3(lst):
/ pre>
return lst [1:] == lst [: - 1]
这三个版本之间的区别是:
- code> checkEqual2 内容必须可哈希。
- $ b
checkEqual1
和checkEqual2
可以使用任何迭代器,但checkEqual3
必须接受序列输入,通常是具体容器,如列表或元组。
checkEqual1 $>
- 由于
checkEqual2
包含更多的Python代码,因此效率较低。和checkEqual3
始终执行O(N)复制操作,如果大部分输入将返回False,则它们将需要更长时间。
checkEqual2
和checkEqual3
不能轻易改为采用比较a是b
而不是a == b
。
timeit
结果,对于Python 2.7和(只有s1,s4,s7,s9应该返回True)s1 = [1] * 5000
s2 = [1] * 4999 + [2]
s3 = [2] + [1] 4999
s4 = [set([9])] * 5000
s5 = [set([9])] * 4999 + [set([10])]
s6 = [set ([10])] + [set([9])] * 4999
s7 = [1,1]
s8 = [1,2]
s9 = []
我们得到
| checkEqual1 | checkEqual2 | checkEqual3 | checkEqualIvo | checkEqual6502 |
| ----- | ------------- | ------------- | ----------- --- | --------------- | ---------------- |
| s1 | 1.19毫秒| 348 usec | 183 usec | 51.6 usec | 121 usec |
| s2 | 1.17毫秒| 376 usec | 185 usec | 50.9 usec | 118 usec |
| s3 | 4.17 usec | 348 usec | 120 usec | 264 usec | 61.3 usec |
| | | | | | |
| s4 | 1.73毫秒| | 182 usec | 50.5 usec | 121 usec |
| s5 | 1.71毫秒| | 181 usec | 50.6 usec | 125 usec |
| s6 | 4.29 usec | | 122usec | 423 usec | 61.1 usec |
| | | | | | |
| s7 | 3.1 usec | 1.4 usec | 1.24 usec | 0.932 usec | 1.92 usec |
| s8 | 4.07 usec | 1.54 usec | 1.28 usec | 0.997 usec | 1.79 usec |
| s9 | 5.91 usec | 1.25 usec | 0.749 usec | 0.407 usec | 0.386 usec |
注意:
code>#http://stackoverflow.com/q/3844948/
def checkEqualIvo(lst):
return not lst或lst.count(lst [0])== len )
#http://stackoverflow.com/q/3844931/
def checkEqual6502(lst):
return not lst或[lst [0]] * len )== lst
I need the following function:
Input: a
list
Output:
True
if all elements in the input list evaluate as equal to each other using the standard equality operator;False
otherwise.
Performance: of course, I prefer not to incur any unnecessary overhead.
I feel it would be best to:
- iterate through the list
- compare adjacent elements
- and
AND
all the resulting Boolean values
But I'm not sure what's the most Pythonic way to do that.
EDIT:
Thank you for all the great answers. I rated up several, and it was really hard to choose between @KennyTM and @Ivo van der Wijk solutions.
The lack of short-circuit feature only hurts on a long input (over ~50 elements) that have unequal elements early on. If this occurs often enough (how often depends on how long the lists might be), the short-circuit is required. The best short-circuit algorithm seems to be @KennyTM checkEqual1
. It pays, however, a significant cost for this:
- up to 20x in performance nearly-identical lists
- up to 2.5x in performance on short lists
If the long inputs with early unequal elements don't happen (or happen sufficiently rarely), short-circuit isn't required. Then, by far the fastest is @Ivo van der Wijk solution.
General method:
def checkEqual1(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == rest for rest in iterator)
One-liner:
def checkEqual2(iterator):
return len(set(iterator)) <= 1
Also one-liner:
def checkEqual3(lst):
return lst[1:] == lst[:-1]
The difference between the 3 versions are that:
- In
checkEqual2
the content must be hashable. checkEqual1
andcheckEqual2
can use any iterators, butcheckEqual3
must take a sequence input, typically concrete containers like a list or tuple.checkEqual1
stops as soon as a difference is found.- Since
checkEqual1
contains more Python code, it is less efficient when many of the items are equal in the beginning. - Since
checkEqual2
andcheckEqual3
always perform O(N) copying operations, they will take longer if most of your input will return False. checkEqual2
andcheckEqual3
can't be easily changed to adopt to comparea is b
instead ofa == b
.
timeit
result, for Python 2.7 and (only s1, s4, s7, s9 should return True)
s1 = [1] * 5000
s2 = [1] * 4999 + [2]
s3 = [2] + [1]*4999
s4 = [set([9])] * 5000
s5 = [set([9])] * 4999 + [set([10])]
s6 = [set([10])] + [set([9])] * 4999
s7 = [1,1]
s8 = [1,2]
s9 = []
we get
| checkEqual1 | checkEqual2 | checkEqual3 | checkEqualIvo | checkEqual6502 |
|-----|-------------|-------------|--------------|---------------|----------------|
| s1 | 1.19 msec | 348 usec | 183 usec | 51.6 usec | 121 usec |
| s2 | 1.17 msec | 376 usec | 185 usec | 50.9 usec | 118 usec |
| s3 | 4.17 usec | 348 usec | 120 usec | 264 usec | 61.3 usec |
| | | | | | |
| s4 | 1.73 msec | | 182 usec | 50.5 usec | 121 usec |
| s5 | 1.71 msec | | 181 usec | 50.6 usec | 125 usec |
| s6 | 4.29 usec | | 122 usec | 423 usec | 61.1 usec |
| | | | | | |
| s7 | 3.1 usec | 1.4 usec | 1.24 usec | 0.932 usec | 1.92 usec |
| s8 | 4.07 usec | 1.54 usec | 1.28 usec | 0.997 usec | 1.79 usec |
| s9 | 5.91 usec | 1.25 usec | 0.749 usec | 0.407 usec | 0.386 usec |
Note:
# http://stackoverflow.com/q/3844948/
def checkEqualIvo(lst):
return not lst or lst.count(lst[0]) == len(lst)
# http://stackoverflow.com/q/3844931/
def checkEqual6502(lst):
return not lst or [lst[0]]*len(lst) == lst
这篇关于检查列表中的所有元素是否相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!