Check if all elements in a list are identical

algorithm, comparison, python

Solution

Use `itertools.groupby` (see the `itertools` recipes):

from itertools import groupby

def all_equal(iterable):
    g = groupby(iterable)
    return next(g, True) and not next(g, False)

or without `groupby`:

def all_equal(iterator):
    iterator = iter(iterator)
    try:
        first = next(iterator)
    except StopIteration:
        return True
    return all(first == x for x in iterator)

There are a number of alternative one-liners you might consider:

Converting the input to a set and checking that it only has one or zero (in case the input is empty) items

def all_equal2(iterator):
    return len(set(iterator)) <= 1

Comparing against the input list without the first item

def all_equal3(lst):
    return lst[:-1] == lst[1:]

Counting how many times the first item appears in the list

def all_equal_ivo(lst):
    return not lst or lst.count(lst[0]) == len(lst)

Comparing against a list of the first element repeated

def all_equal_6502(lst):
    return not lst or [lst[0]]*len(lst) == lst

But they have some downsides, namely:

- `all_equal` and `all_equal2` can use any iterators, but the others must take a sequence input, typically concrete containers like a list or tuple.

- `all_equal` and `all_equal3` stop as soon as a difference is found (what is called "short circuit"), whereas all the alternatives require iterating over the entire list, even if you can tell that the answer is `False` just by looking at the first two elements.

- In `all_equal2` the content must be hashable. A list of lists will raise a `TypeError` for example.

- `all_equal2` (in the worst case) and `all_equal_6502` create a copy of the list, meaning you need to use double the memory.

On Python 3.9, using `perfplot`, we get these timings (lower `Runtime [s]` is better):

Problem

I need a function which takes in a `list` and outputs `True` if all elements in the input list evaluate as equal to each other using the standard equality operator and `False` otherwise. I feel it would be best to iterate through the list comparing adjacent elements and then `AND` all the resulting Boolean values. But I'm not sure what's the most Pythonic way to do that.

Original source

Related problems