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

我觉得最好是遍历列表,比较相邻的元素,然后与所有结果布尔值。但我不知道最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).

当然,可读性也有好处。

其他回答

关于使用reduce()和lambda。这里有一个工作代码,我个人认为比其他一些答案更好。

reduce(lambda x, y: (x[1]==y, y), [2, 2, 2], (True, 2))

返回一个元组,其中第一个值是布尔值,如果所有项都相同或不相同。

不管怎样,这是最近在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)个额外的内存来进行检查。

换句话说,我不能把提出这个解决方案的功劳占为己有,甚至我也不能把找到它的功劳占为己有。

这是另一个选项,对于长列表,比len(set(x))==1快(使用短路)

def constantList(x):
    return x and [x[0]]*len(x) == x

您可以使用.nunique()来查找列表中唯一项的数量。

def identical_elements(list):
    series = pd.Series(list)
    if series.nunique() == 1: identical = True
    else:  identical = False
    return identical



identical_elements(['a', 'a'])
Out[427]: True

identical_elements(['a', 'b'])
Out[428]: False

你可以:

reduce(and_, (x==yourList[0] for x in yourList), True)

python让你导入operator.and_这样的操作符是相当烦人的。从python3开始,还需要导入functools.reduce。

(您不应该使用此方法,因为如果它发现不相等的值,它不会中断,而是会继续检查整个列表。这里只是作为完整性的回答。)