Python 检查列表中的所有元素是否相同
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3844801/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if all elements in a list are identical
提问by max
I need the following function:
我需要以下功能:
Input: a list
输入:一个list
Output:
输出:
Trueif all elements in the input list evaluate as equal to each other using the standard equality operator;Falseotherwise.
True如果输入列表中的所有元素使用标准相等运算符评估为彼此相等;False除此以外。
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
ANDall the resulting Boolean values
- 遍历列表
- 比较相邻元素
- 以及
AND所有结果布尔值
But I'm not sure what's the most Pythonic way to do that.
但我不确定最 Pythonic 的方法是什么。
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:
缺少短路功能只会对早期具有不相等元素的长输入(超过 50 个元素)造成伤害。如果这种情况发生得足够频繁(频率取决于列表的长度),则需要短路。最好的短路算法似乎是 @KennyTM checkEqual1。然而,它为此付出了巨大的代价:
- up to 20x in performance nearly-identical lists
- up to 2.5x in performance on short lists
- 在性能几乎相同的列表中高达 20 倍
- 在短名单上的性能高达 2.5 倍
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.
如果具有早期不相等元素的长输入不发生(或发生得足够少),则不需要短路。然后,到目前为止最快的是@Ivo van der Wijk 解决方案。
采纳答案by kennytm
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:
3个版本的区别在于:
- In
checkEqual2the content must be hashable. checkEqual1andcheckEqual2can use any iterators, butcheckEqual3must take a sequence input, typically concrete containers like a list or tuple.checkEqual1stops as soon as a difference is found.- Since
checkEqual1contains more Python code, it is less efficient when many of the items are equal in the beginning. - Since
checkEqual2andcheckEqual3always perform O(N) copying operations, they will take longer if most of your input will return False. - For
checkEqual2andcheckEqual3it's harder to adapt comparison froma == btoa is b.
- 在
checkEqual2内容中必须是可散列的。 checkEqual1并且checkEqual2可以使用任何迭代器,但checkEqual3必须采用序列输入,通常是像列表或元组这样的具体容器。checkEqual1一旦发现差异就停止。- 由于
checkEqual1包含更多 Python 代码,当许多项在开始时相等时效率较低。 - 由于
checkEqual2并且checkEqual3始终执行 O(N) 复制操作,如果您的大部分输入将返回 False,它们将花费更长的时间。 - 对于
checkEqual2并且checkEqual3更难适应从a == b到 的比较a is b。
timeitresult, for Python 2.7 and (only s1, s4, s7, s9 should return True)
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 = []
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
回答by machineghost
Doubt this is the "most Pythonic", but something like:
怀疑这是“最 Pythonic”,但类似于:
>>> falseList = [1,2,3,4]
>>> trueList = [1, 1, 1]
>>>
>>> def testList(list):
... for item in list[1:]:
... if item != list[0]:
... return False
... return True
...
>>> testList(falseList)
False
>>> testList(trueList)
True
would do the trick.
会做的伎俩。
回答by codaddict
You can convert the list to a set. A set cannot have duplicates. So if all the elements in the original list are identical, the set will have just one element.
您可以将列表转换为集合。一个集合不能有重复项。因此,如果原始列表中的所有元素都相同,则该集合将只有一个元素。
if len(sets.Set(input_list)) == 1
// input_list has all identical elements.
回答by pyfunc
>>> a = [1, 2, 3, 4, 5, 6]
>>> z = [(a[x], a[x+1]) for x in range(0, len(a)-1)]
>>> z
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
# Replacing it with the test
>>> z = [(a[x] == a[x+1]) for x in range(0, len(a)-1)]
>>> z
[False, False, False, False, False]
>>> if False in z : Print "All elements are not equal"
回答by Jerub
This is a simple way of doing it:
这是一个简单的方法:
result = mylist and all(mylist[0] == elem for elem in mylist)
This is slightly more complicated, it incurs function call overhead, but the semantics are more clearly spelled out:
这稍微复杂一些,它会产生函数调用开销,但语义更清楚地说明:
def all_identical(seq):
if not seq:
# empty list is False.
return False
first = seq[0]
return all(first == elem for elem in seq)
回答by 6502
This is another option, faster than len(set(x))==1for long lists (uses short circuit)
这是另一种选择,比len(set(x))==1长列表更快(使用短路)
def constantList(x):
return x and [x[0]]*len(x) == x
回答by Ivo van der Wijk
A solution faster than using set() that works on sequences (not iterables) is to simply count the first element. This assumes the list is non-empty (but that's trivial to check, and decide yourself what the outcome should be on an empty list)
比使用 set() 处理序列(不是可迭代对象)更快的解决方案是简单地计算第一个元素。这假设列表是非空的(但检查起来很简单,并决定自己在空列表上的结果应该是什么)
x.count(x[0]) == len(x)
some simple benchmarks:
一些简单的基准:
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*5000', number=10000)
1.4383411407470703
>>> timeit.timeit('len(set(s1))<=1', 's1=[1]*4999+[2]', number=10000)
1.4765670299530029
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*5000', number=10000)
0.26274609565734863
>>> timeit.timeit('s1.count(s1[0])==len(s1)', 's1=[1]*4999+[2]', number=10000)
0.25654196739196777
回答by itertool
def allTheSame(i):
j = itertools.groupby(i)
for k in j: break
for k in j: return False
return True
Works in Python 2.4, which doesn't have "all".
在 Python 2.4 中工作,它没有“全部”。
回答by Robert Rossney
I'd do:
我会做:
not any((x[i] != x[i+1] for i in range(0, len(x)-1)))
as anystops searching the iterable as soon as it finds a Truecondition.
asany一旦找到True条件就停止搜索可迭代对象。
回答by ninjagecko
The simplest and most elegant way is as follows:
最简单最优雅的方式如下:
all(x==myList[0] for x in myList)
(Yes, this even works with the empty list! This is because this is one of the few cases where python has lazy semantics.)
(是的,这甚至适用于空列表!这是因为这是 python 具有惰性语义的少数情况之一。)
Regarding performance, this will fail at the earliest possible time, so it is asymptotically optimal.
关于性能,这将在尽可能早的时间内失败,因此它是渐近最优的。

