我需要一个函数,它接受一个列表并输出True,如果输入列表中的所有元素使用标准相等运算符计算彼此相等,否则输出False。
我觉得最好是遍历列表,比较相邻的元素,然后与所有结果布尔值。但我不知道最python的方法是什么。
我需要一个函数,它接受一个列表并输出True,如果输入列表中的所有元素使用标准相等运算符计算彼此相等,否则输出False。
我觉得最好是遍历列表,比较相邻的元素,然后与所有结果布尔值。但我不知道最python的方法是什么。
当前回答
还有一个纯Python递归选项:
def checkEqual(lst):
if len(lst)==2 :
return lst[0]==lst[1]
else:
return lst[0]==lst[1] and checkEqual(lst[1:])
然而,由于某些原因,它在某些情况下比其他选项慢两个数量级。从C语言的角度来看,我希望这更快,但事实并非如此!
另一个缺点是Python中有递归限制,在这种情况下需要进行调整。比如用这个。
其他回答
我最后写了这样一句话
from itertools import starmap, pairwise
all(starmap(eq, (pairwise(x)))
关于使用reduce()和lambda。这里有一个工作代码,我个人认为比其他一些答案更好。
reduce(lambda x, y: (x[1]==y, y), [2, 2, 2], (True, 2))
返回一个元组,其中第一个值是布尔值,如果所有项都相同或不相同。
使用itertools的更多版本。groupby,我发现它比原来的更清晰(下面有更多关于它的信息):
def all_equal(iterable):
g = groupby(iterable)
return not any(g) or not any(g)
def all_equal(iterable):
g = groupby(iterable)
next(g, None)
return not next(g, False)
def all_equal(iterable):
g = groupby(iterable)
return not next(g, False) or not next(g, False)
以下是来自Itertools Recipes的原始版本:
def all_equal(iterable):
g = groupby(iterable)
return next(g, True) and not next(g, False)
注意,下一个(g, True)总是True(它不是一个非空元组就是True)。这意味着它的值不重要。它的执行纯粹是为了推进groupby迭代器。但是在返回表达式中包含它会导致读者认为它的值在那里被使用。因为它没有,我发现这是误导和不必要的复杂。我上面的第二个版本将next(g, True)视为它的实际用途,作为一个我们不关心其值的语句。
我的第三个版本走了一个不同的方向,并使用了第一个next的值(g, False)。如果根本没有第一个组(即,如果给定的可迭代对象为“空”),则该解决方案立即返回结果,甚至不检查是否有第二个组。
我的第一个解决方案基本上和第三个一样,只是使用任何一个。两种解决方案都读作“所有元素都是相等的……”没有第一组,也没有第二组。”
基准测试结果(虽然速度并不是我在这里的重点,但清晰才是重点,在实践中,如果有许多相等的值,大多数时间可能由组自己花费,减少了这些差异的影响):
Python 3.10.4 on my Windows laptop:
iterable = ()
914 ns 914 ns 916 ns use_first_any
917 ns 925 ns 925 ns use_first_next
1074 ns 1075 ns 1075 ns next_as_statement
1081 ns 1083 ns 1084 ns original
iterable = (1,)
1290 ns 1290 ns 1291 ns next_as_statement
1303 ns 1307 ns 1307 ns use_first_next
1306 ns 1307 ns 1309 ns use_first_any
1318 ns 1319 ns 1320 ns original
iterable = (1, 2)
1463 ns 1464 ns 1467 ns use_first_any
1463 ns 1463 ns 1467 ns next_as_statement
1477 ns 1479 ns 1481 ns use_first_next
1487 ns 1489 ns 1492 ns original
Python 3.10.4 on a Debian Google Compute Engine instance:
iterable = ()
234 ns 234 ns 234 ns use_first_any
234 ns 235 ns 235 ns use_first_next
264 ns 264 ns 264 ns next_as_statement
265 ns 265 ns 265 ns original
iterable = (1,)
308 ns 308 ns 308 ns next_as_statement
315 ns 315 ns 315 ns original
316 ns 316 ns 317 ns use_first_any
317 ns 317 ns 317 ns use_first_next
iterable = (1, 2)
361 ns 361 ns 361 ns next_as_statement
367 ns 367 ns 367 ns original
384 ns 385 ns 385 ns use_first_next
386 ns 387 ns 387 ns use_first_any
基准测试代码:
from timeit import timeit
from random import shuffle
from bisect import insort
from itertools import groupby
def original(iterable):
g = groupby(iterable)
return next(g, True) and not next(g, False)
def use_first_any(iterable):
g = groupby(iterable)
return not any(g) or not any(g)
def next_as_statement(iterable):
g = groupby(iterable)
next(g, None)
return not next(g, False)
def use_first_next(iterable):
g = groupby(iterable)
return not next(g, False) or not next(g, False)
funcs = [original, use_first_any, next_as_statement, use_first_next]
for iterable in (), (1,), (1, 2):
print(f'{iterable = }')
times = {func: [] for func in funcs}
for _ in range(1000):
shuffle(funcs)
for func in funcs:
number = 1000
t = timeit(lambda: func(iterable), number=number) / number
insort(times[func], t)
for func in sorted(funcs, key=times.get):
print(*('%4d ns ' % round(t * 1e9) for t in times[func][:3]), func.__name__)
print()
不管怎样,这是最近在python想法邮件列表中出现的。事实证明,已经有一个itertools配方可以做到这一点
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)
据说它的性能非常好,有一些不错的属性。
短路:一旦发现第一个不相等的项,它就会停止从可迭代对象中消费项目。 不要求项是可哈希的。 它是懒惰的,只需要O(1)个额外的内存来进行检查。
换句话说,我不能把提出这个解决方案的功劳占为己有,甚至我也不能把找到它的功劳占为己有。
def allTheSame(i):
j = itertools.groupby(i)
for k in j: break
for k in j: return False
return True
适用于Python 2.4,它没有“all”。