max*_*max 351 python algorithm comparison
我需要以下功能:
输入:alist
输出:
True
如果输入列表中的所有元素使用标准相等运算符评估为彼此相等; False
除此以外.性能:当然,我不希望招致任何不必要的开销.
我觉得最好是:
AND
所有结果布尔值但我不确定最恐怖的方式是什么.
编辑:
谢谢你所有的好答案.我评价了几个,而且很难在@KennyTM和@Ivo van der Wijk解决方案之间做出选择.
缺少短路功能只会对早期具有不相等元素的长输入(超过约50个元素)造成伤害.如果这种情况经常发生(通常取决于列表的长度),则需要进行短路.最好的短路算法似乎是@KennyTM checkEqual1
.然而,它为此付出了巨大的代价:
如果早期不等元素的长输入没有发生(或很少发生),则不需要短路.然后,到目前为止最快的是@Ivo van der Wijk解决方案.
ken*_*ytm 378
一般方法:
def checkEqual1(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == rest for rest in iterator)
Run Code Online (Sandbox Code Playgroud)
一内胆:
def checkEqual2(iterator):
return len(set(iterator)) <= 1
Run Code Online (Sandbox Code Playgroud)
单行:
def checkEqual3(lst):
return lst[1:] == lst[:-1]
Run Code Online (Sandbox Code Playgroud)
3个版本之间的区别在于:
checkEqual2
内容必须是可以清洗的.checkEqual1
并且checkEqual2
可以使用任何迭代器,但checkEqual3
必须采用序列输入,通常是具体的容器,如列表或元组.checkEqual1
一发现差异就会停止.checkEqual1
包含更多Python代码,因此在开始时许多项目相同时效率较低.checkEqual2
并且checkEqual3
始终执行O(N)复制操作,如果大多数输入将返回False,则它们将花费更长时间.checkEqual2
和checkEqual3
它很难适应从比较a == b
到a is 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 = []
Run Code Online (Sandbox Code Playgroud)
我们得到
| 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 |
Run Code Online (Sandbox Code Playgroud)
注意:
# 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
Run Code Online (Sandbox Code Playgroud)
Ivo*_*ijk 273
比使用在序列(而不是迭代)上工作的set()更快的解决方案是简单地计算第一个元素.这假定列表是非空的(但这很容易检查,并确定自己在空列表中应该是什么结果)
x.count(x[0]) == len(x)
Run Code Online (Sandbox Code Playgroud)
一些简单的基准:
>>> 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
Run Code Online (Sandbox Code Playgroud)
nin*_*cko 140
最简单,最优雅的方式如下:
all(x==myList[0] for x in myList)
Run Code Online (Sandbox Code Playgroud)
(是的,这甚至适用于空列表!这是因为这是python具有惰性语义的少数情况之一.)
关于性能,这将在尽可能早的时候失败,因此它是渐近最优的.
cba*_*wat 42
一组比较工作:
len(set(the_list)) == 1
Run Code Online (Sandbox Code Playgroud)
使用set
删除所有重复元素.
cod*_*ict 25
您可以将列表转换为集合.一套不能有重复.因此,如果原始列表中的所有元素都相同,则该集合将只有一个元素.
if len(sets.Set(input_list)) == 1
// input_list has all identical elements.
Run Code Online (Sandbox Code Playgroud)
mgi*_*son 18
为了它的价值,最近在python-ideas邮件列表中提出了这个问题.事实证明,有一个itertools配方已经做到这一点:1
def all_equal(iterable):
"Returns True if all the elements are equal to each other"
g = groupby(iterable)
return next(g, True) and not next(g, False)
Run Code Online (Sandbox Code Playgroud)
据说它表现得非常好,并且有一些不错的属性.
1换句话说,我不能居功能想出解决方案-我也不能采取信贷,甚至找到它.
Chr*_*cio 16
将列表转换为集合时,将删除重复的元素.因此,如果转换集的长度为1,则表示所有元素都相同.
len(set(input_list))==1
Run Code Online (Sandbox Code Playgroud)
这是一个例子
>>> a = ['not', 'the', 'same']
>>> b = ['same', 'same', 'same']
>>> len(set(a))==1 # == 3
False
>>> len(set(b))==1 # == 1
True
Run Code Online (Sandbox Code Playgroud)
这将比较(等价)输入列表的第一个元素与列表中的每个其他元素.如果全部等效,则返回True,否则返回False.
all(element==input_list[0] for element in input_list)
Run Code Online (Sandbox Code Playgroud)
这是一个例子
>>> a = [1, 2, 3, 4, 5]
>>> b = [1, 1, 1, 1, 1]
>>> all(number==a[0] for number in a)
False
>>> all(number==b[0] for number in b)
True
Run Code Online (Sandbox Code Playgroud)
PS如果要检查整个列表是否等于某个值,则可以为input_list [0]指定值.
650*_*502 11
这是另一种选择,比len(set(x))==1
长列表更快(使用短路)
def constantList(x):
return x and [x[0]]*len(x) == x
Run Code Online (Sandbox Code Playgroud)
这是一种简单的方法:
result = mylist and all(mylist[0] == elem for elem in mylist)
Run Code Online (Sandbox Code Playgroud)
这稍微复杂一点,它会产生函数调用开销,但语义更明确:
def all_identical(seq):
if not seq:
# empty list is False.
return False
first = seq[0]
return all(first == elem for elem in seq)
Run Code Online (Sandbox Code Playgroud)