Search code examples
pythonfunctional-programming

Python functional method of checking that all elements in a list are equal


I am trying to find a functional method which is available in Python which can be used to check if all elements in a list are equal. Instinctively, I feel that this should be possible.

My objective is to build a functional solution to solve the problem of checking if all values in list are equal.

If you search for similar questions on this site you will find both questions and answers, written for Python, but none of these take a functional approach.


Solution

  • Thanks to others for helping with this. The TL;DR answer: use starmap.

    Rather than doing everything all at once using a single functional function call, it splits the operations into two steps.

    • The first step is to check that adjacent pairs of elements are equal, producing a new list (actually: iterator with yielding behavior) containing boolean values
    • The second step is to check if all of the boolean values are true

    It seems like the one obvious functional solution, which results in a clean code.

    input_list [1, 1, 1, 1, 1, 1, 1]
    
    import operator
    from itertools import pairwise
    from itertools import starmap
    
    def all_items_in_list_are_equal(l: list) -> bool:
    
        all_items_are_equal = \
            all(
                starmap(
                    operator.eq,
                    pairwise(l)
                )
            )
    
        return all_items_are_equal
    

    This solution is:

    • lazy evaluated
    • requires only operator.eq for the types contained within l
    • does not require __hash__

    It works by producing a pairwise iterator pairwise(l) which returns pairs of adjacent elements in the list l as a tuple.

    The tuple is expanded into pairs of arguments by starmap. operator.eq expects two arguments, so a single argument of type pair will not do. We use starmap to apply operator.eq to every pair of values yield by the iterator.

    • starmap is to map what func(*args) is to func(a, b, c, ...)

    Finally, all checks that all elements of an iterable are True.

    See edits for history