Cómo Determinar si Todos los Elementos de una Lista son Iguales

Aunque este post lleva un título relacionado con las listas, no trata en realidad sobre estas, trata sobre la habilidad de los programadores para resolver problemas y de cómo influye en ella, el conocimiento que estos tengan del lenguaje (en nuestro caso de Python).

Una de las habilidades más deseables (si no la más) en un buen programador y casi en cualquier profesión, es sin dudas la capacidad de resolver problemas. La resolución de problemas abarca una serie de técnicas conocidas como algoritmos, heurística, análisis de causa raíz (ACR), entre otros. En ciencias de la computación, la resolución de problemas es parte de un proceso más amplio que abarca la determinación/identificación de problemas, recopilación y deduplicación de datos, análisis, diagnóstico, y reparación. Ahora bien, ¿cómo influye el conocimiento que tengamos del lenguaje de un programación determinado en nuestra capacidad para resolver problemas? Para arrojar un poco de luz sobre el tema, tomaremos como Conejillo de Indias el problema de ¿Cómo determinar si todos los elementos de una lista son iguales o no?

Nota: parte del código que incluimos en este post ha sido adaptado del Blog Post Determining if all Elements in a List are the Same in Python.

Un Primer Acercamiento

Como premisa y en aras de la simplicidad, vamos a asumir que se trata de una lista no vacía que solo contiene números enteros. Partiendo de esto, puedo decir que cando me enfrenté por primera vez a este problema, mi pensamiento fue: “…ahora debo comparar todos los elementos de la lista entre sí para ver si son iguales o no… hmm, esto lo puedo hacer con un ciclo for…”. Luego de un rato dándole vueltas al asunto llegué a esta solución:

def all_the_same(elements):

    first = elements[0]

    for item in elements:

        if first != item:

            return False

    return True

Esto es lo más elemental que un programador cualquiera pudiera hacer teniendo un mínimo de conocimientos sobre Python, su sintaxis, sus tipos de datos y sus estructuras de control de flujo. Bien, ya está resuelto el problema, pero este post se trata de creatividad en la solución de problemas, así que veamos que más se nos ocurre.

Otras Soluciones

  1. Podríamos ordenar la lista y comparar el primero y el último elementos, de la forma siguiente:

def all_equal(elements):

    elements.sort()

    return elements[0] == elements[-1]

  1. También podemos compara la longitud de la lista con el número de veces que se repite el primer elemento de la misma:

def all_the_same(elements):

    return len(elements) == elements.count(elements[0])

  1. La tercera solución aprovecha dos rasgos fundamentales de Python: la comparación de listas con el operador “==”,

>>>[1, 1, 1] == [1, 1, 1]

True

>>> [1, 1, 0] == [0, 1, 1]

False

y la repetición que se obtiene al multiplicar una lista por un número entero:

>> [1] * 3 [1, 1, 1]

>> [1] * 5 [1, 1, 1, 1, 1]

>> [1, 2] * 3 [1, 2, 1, 2, 1, 2]

def all_the_same(elements):

    return [elements[0]] * len(elements) == elements

  1. Los conjuntos (set) en Python son estructuras de datos que siempre almacenan secuencias de elementos únicos. Si aprovechamos característica de los conjuntos, podemos llegar a una solución bien simple:

def all_the_same(elements):

    return len(set(elements)) == 1

  1. Otra solución podría venir de la mano de la función integrada (built-in) all() que podemos emplear para saber si todos los elementos en un iterable son verdaderos.

>>> all([1, 2, 0, True])

False #(0 isn’t true)

>>> all([1, 2, None, True])

False #(None isn’t true)

>>> all([1, 2, False, True])

False

>>> all([1, 2, 0.1, True])

True

De este modo podemos escribir:

def all_the_same(elements):

    first, *rest = elements the_same = (x == first for x in rest)

    return all(the_same)

  1. Una solución muy parecida a la anterior se puede implementar empleando las funciones integradas iter() y next(). Con iter() creamos un iterador y con next() avanzamos sobre cada uno de los elementos de este:

def all_the_same(elements):

    it = iter(elements)

    first = next(el)

    return all(element == first for element in it)

Esto es posible gracias a que los iteradores en Python se “agotan” o dicho de otra forma, se puede iterar sobre ellos una única vez (single pass iterators).

Es por esto que luego de haber hecho first = next(el) ya it no volverá a repetir el primer elemento de elements.

>>> it = iter([1, 2, 3])

>>> first = next(el, None)

>>> print(first)

1

>>> for i in it:

>>> print(i)

2

3

  1. La función integrada zip() de Python nos permite combinar los i-ésimos elementos de dos secuencias de entrada:

>>> x = [1, 2, 3]

>>> y = [10, 11]

>>> list(zip(x, y))

[(1, 10), (2, 11)]

Hacemos notar que el resultado de la función zip() tendrá un número de elementos igual al número de elementos de la secuencia más corta. Partiendo de estas ideas la implementación de la solución al problema planteado quedaría de la forma siguiente:

def all_the_same(elements):

    return all(x == y for x, y in zip(elements, elements[1:]))

En este caso es necesario hacer que el segundo argumento de zip() sea una copia de elements sin su primer elemento (elements[1:]) en lugar de elements, pues de este modo corremos los elementos a comparar para no caer en el error de comparar el mismo elemento en todos los casos.

  1. Otra solución puede derivarse del empleo de la clase Counter([iterable-or-mapping]) que podemos encontrar en el módulo collections de la librería estándar. Counter crea un diccionario cuyas claves son los elementos de la secuencia que le suministramos como argumento y sus valores contienen información acerca del número de veces que cada elemento se repite en la secuencia de entrada.

>>> from collections import Counter

>>> a = [1, 1, 1, 2, 2, 3]

>>> Counter(a)

Counter({1: 3, 2: 2, 3: 1})

Consecuentemente, si el diccionario resultante contiene dos o más, entonces hay al menos dos elementos diferentes en la lista.

def all_the_same(elements):

    from collections import Counter

    return not len(list(Counter(elements))) > 1

Conclusión

Aunque la lista de soluciones anteriores pudiera ser mucho más extensa, creo que hasta aquí es más que suficiente como para dejar entrever, en primer lugar, la versatilidad y flexibilidad de Python como lenguaje de programación. En segundo lugar, creo que la lección más importante que podemos sacar de todos estos acercamientos al problema de “Cómo determinar si todos los elementos de una lista son iguales”, es que la solución que demos a un determinado problema de programación dependerá, en primera instancia, de nuestra imaginación y de nuestra creatividad a la hora de resolver problemas, pero en mi humilde opinión, creo que al menos en la programación, nuestra capacidad para resolver problemas va a estar casi siempre condicionada, o más bien potenciada, por el grado de dominio del lenguaje que hayamos logrado alcanzar. Veámoslo de este modo: sin conocer las características de Python que sirven de sustento a cada una de las soluciones anteriores, nunca habríamos podido llegar a formularlas y quizás nos hubiésemos quedado con la primera y más básica alternativa. Con esto en mete, solo nos queda una sugerencia: proponernos dominar a fondo el lenguaje, para que, como se dice en buen cubano, nadie venga a meternos cuentos.

Y esto es todo por ahora, si este artículo te resultó interesante y/o útil, compártelo para que otros también puedan acceder a él. Déjanos tus comentarios y podremos mejorar nuestros contenidos.

Gracias de antemano,

lpozo

1 comentario

    • LordFord en 25 septiembre, 2018 a las 12:17 pm

    Súper bueno esto !!! Un abrazo…

Los comentarios han sido desactivados.