我需要一个函数,如果输入列表中的所有元素都使用标准相等运算符和其他方式评估为彼此相等,则它接受 a 并输出。list
True
False
我觉得最好遍历列表,比较相邻元素,然后比较所有生成的布尔值。但我不确定什么是最Pythonic的方式。AND
使用(见食谱):itertools.groupby
itertools
from itertools import groupby
def all_equal(iterable):
g = groupby(iterable)
return next(g, True) and not next(g, False)
或不 :groupby
def all_equal(iterator):
iterator = iter(iterator)
try:
first = next(iterator)
except StopIteration:
return True
return all(first == x for x in iterator)
您可以考虑使用多种替代单行代码:
def all_equal2(iterator):
return len(set(iterator)) <= 1
def all_equal3(lst):
return lst[:-1] == lst[1:]
def all_equal_ivo(lst):
return not lst or lst.count(lst[0]) == len(lst)
def all_equal_6502(lst):
return not lst or [lst[0]]*len(lst) == lst
但它们有一些缺点,即:
all_equal
并且可以使用任何迭代器,但其他迭代器必须采用序列输入,通常是列表或元组等具体容器。all_equal2
all_equal
并在发现差异后立即停止(所谓的“短路”),而所有替代方案都需要遍历整个列表,即使您可以通过查看前两个元素来判断答案。all_equal3
False
all_equal2
TypeError
all_equal2
(在最坏的情况下)并创建列表的副本,这意味着您需要使用双倍的内存。all_equal_6502
在 Python 3.9 上,使用 ,我们得到这些计时(越低越好):perfplot
Runtime [s]
比使用适用于序列(不是可迭代对象)的 set() 更快的解决方案是简单地计算第一个元素。这假设列表是非空的(但这很容易检查,并自己决定空列表上的结果应该是什么)
x.count(x[0]) == len(x)
一些简单的基准:
>>> 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
[编辑:这个答案稍后解决了目前投票最多(这是一个很好的答案)的答案。itertools.groupby
在不重写程序的情况下,最渐近性能和最易读的方式如下:
all(x==myList[0] for x in myList)
(是的,这甚至适用于空列表!这是因为这是python具有惰性语义的少数情况之一。
这将在尽可能早的时间失败,因此它是渐近最优的(预期时间大约是O(#uniques)而不是O(N),但最坏情况的时间仍然是O(N))。这是假设您以前没有看过数据…
(如果你关心性能,但不太关心性能,你可以先做通常的标准优化,比如把常量吊出循环,为边缘情况添加笨拙的逻辑,尽管这是python编译器最终可能会学会怎么做的事情,因此除非绝对必要,否则不应该这样做, 因为它破坏了可读性,以获得最小的收益。myList[0]
如果您更关心性能,这是上述速度的两倍,但更详细一些:
def allEqual(iterable):
iterator = iter(iterable)
try:
firstItem = next(iterator)
except StopIteration:
return True
for x in iterator:
if x!=firstItem:
return False
return True
如果你更关心性能(但不足以重写你的程序),请使用当前投票最多的答案,它的速度是它的两倍,因为它可能是优化的 C 代码。(根据文档,它应该(类似于这个答案)没有任何内存开销,因为惰性生成器永远不会被评估到列表中……哪一个可能会担心,但伪代码显示分组的“列表”实际上是惰性生成器。itertools.groupby
allEqual
如果您更关心性能,请继续阅读…
关于性能的旁注,因为其他答案出于某种未知原因在谈论它:
…如果您以前看过数据并且可能使用某种类型的集合数据结构,并且您真的很关心性能,那么您可以通过使用计数器来免费获得 .isAllEqual
() O(1),该计数器
会随着每次插入/删除/等操作而更新,只需检查它是否为 {something:someCount}
即 len(counter.keys())==1
;或者,您可以在单独的变量中保留一个计数器。事实证明,这比其他任何恒定因素都要好。也许你也可以使用python的FFI与你选择的方法一起使用,也许也可以使用启发式方法(比如,如果它是一个带有getitem的序列,然后检查第一个元素,最后一个元素,然后按顺序检查元素)。ctypes
当然,为了可读性,有一些话要说。
模板简介:该模板名称为【Python 检查列表中的所有元素是否相同】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Python】栏目查找您需要的精美模板。