我需要一个函数,它接受一个列表并输出True,如果输入列表中的所有元素使用标准相等运算符计算彼此相等,否则输出False。

我觉得最好是遍历列表,比较相邻的元素,然后与所有结果布尔值。但我不知道最python的方法是什么。


当前回答

这是一个有趣的阅读和思考。谢谢大家! 我不认为任何依赖于纯计数的方法对所有情况都是可靠的。sum也可以工作,但只适用于数字或长度(再次导致计数场景)。

但我喜欢简单,所以我想出了这个:

all(i==lst[c-1] for c, i in enumerate(lst))

或者,我确实认为@kennytm的这个聪明的方法也适用于所有情况(有趣的是,它可能是最快的)。所以我承认它可能比我的好:

[lst[0]]*len(lst) == lst

我认为一个聪明的小奖励也会起作用,因为set消除了重复(聪明是有趣的,但通常不是维护代码的最佳实践)。我认为@kennytm的方法仍然会更快,但只适用于大型列表:

len(set(lst)) == 1

但是Python的简单和聪明是我最喜欢的语言之一。再想一下,如果你必须修改列表,就像我实际上做的那样,因为我正在比较地址(并将删除开头/结尾空格并转换为小写以消除可能的不一致,我的将更适合这项工作)。所以“更好”是主观的,因为我在使用这个词时使用了引号!但是你也可以事先清理列表。

祝你好运!

其他回答

[编辑:这个答案针对当前投票最多的itertools。Groupby(这是一个很好的答案)稍后回答。

在不重写程序的情况下,最具渐近性能和可读性的方法如下:

all(x==myList[0] for x in myList)

(是的,这甚至适用于空列表!这是因为这是python具有惰性语义的少数情况之一。)

这将在尽可能早的时间失败,因此它是渐近最优的(期望时间大约是O(#惟一)而不是O(N),但最坏情况时间仍然是O(N))。这是假设你之前没有看过这些数据……

(如果你关心性能,但不太关心性能,你可以先做通常的标准优化,比如将myList[0]常量从循环中提升出来,并为边缘情况添加笨拙的逻辑,尽管这是python编译器最终可能会学会如何做的事情,因此除非绝对必要,否则不应该这样做,因为它会破坏最小收益的可读性。)

如果你更关心性能,这是上面速度的两倍,但有点啰嗦:

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

如果你更关心性能(但还不足以重写你的程序),请使用当前投票最多的itertools。它的速度是allEqual的两倍,因为它可能是优化的C代码。(根据文档,它应该(类似于这个答案)没有任何内存开销,因为惰性生成器永远不会被计算到列表中…这可能会让人担心,但伪代码表明,分组的“列表”实际上是惰性生成器。)

如果你更关心性能,请继续阅读…


关于性能的旁注,因为其他答案都在谈论它,因为一些未知的原因:

... if you have seen the data before and are likely using a collection data structure of some sort, and you really care about performance, you can get .isAllEqual() for free O(1) by augmenting your structure with a Counter that is updated with every insert/delete/etc. operation and just checking if it's of the form {something:someCount} i.e. len(counter.keys())==1; alternatively you can keep a Counter on the side in a separate variable. This is provably better than anything else up to constant factor. Perhaps you can also use python's FFI with ctypes with your chosen method, and perhaps with a heuristic (like if it's a sequence with getitem, then checking first element, last element, then elements in-order).

当然,可读性也有好处。

我怀疑这是“最python化的”,但类似于:

>>> 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

会成功的。

>>> 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"

可以使用map和lambda吗

lst = [1,1,1,1,1,1,1,1,1]

print all(map(lambda x: x == lst[0], lst[1:]))

或者使用numpy的diff方法:

import numpy as np
def allthesame(l):
    return np.all(np.diff(l)==0)

并呼吁:

print(allthesame([1,1,1]))

输出:

True