La forma más pitónica de comparar dos listas en Python

Problema: Se dan dos listas l1 y l2. Quieres realizar una de las siguientes acciones:

  • 1. Comparación booleana: comparar las listas por elementos y devolver True si la métrica de comparación devuelve True para todos los pares de elementos y False en caso contrario.
  • 2. Diferencia: encontrar la diferencia entre los elementos de la primera lista y la segunda.

Ejemplo: comienzas con dos listas.

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]

# 1. Boolean Comparison
result = False

# 2. Difference
result = [4, 5]

Analicemos las formas más pitónicas de resolver estos problemas. Comenzamos con cinco formas de realizar la comparación booleana y, a continuación, veremos cinco formas de realizar la diferencia simple.

💡 Try It Yourself: Feel free to try all code snippets of this article in our interactive Jupyter notebook. You can find the English version of this article here.

Comparación booleana

Respuesta corta: la forma más pitónica de verificar si dos listas ordenadas l1 y l2 son idénticas es usar el operador l1 == l2 para la comparación de elementos. Si todos los elementos son iguales y la longitud de las listas es la misma, el valor de retorno es True.

Problema: Se dan dos listas l1 y l2. Quieres realizar una comparación booleana: comparar las listas por elementos y devuelve True si su métrica de comparación devuelve True para todos los pares de elementos y, de lo contrario, False.

Ejemplos:

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]
# compare(l1, l2) --> False

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3, 5, 4]
# compare(l1, l2) --> False

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3, 4, 5]
# compare(l1, l2) --> True

Analicemos las formas más pitónicas de resolver este problema. Aquí tienes un rápido repaso interactivo del código:

Ejercicio: Echa un vistazo a todos los métodos y ejecuta el código. ¿Qué preguntas te vienen a la mente? ¿Entiendes cada método?

¡Sigue leyendo para aprender cada método en detalle!

Método 1: comparación simple

No siempre el método más simple es el mejor. ¡Pero para este problema en particular, lo es! El operador de igualdad == compara una lista por elementos; ¡muchos programadores de Python no lo saben!

# 1. Simple Comparison
def method_1(l1, l2):
    return l1 == l2

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]
print(method_1(l1, l2))
# False

Así que, si lo que quieres es conocer la forma más pitónica de resolver este problema, no busques más.

Pero si quieres sumergirte en el maravilloso mundo de Python, aprendiendo diferentes funciones de Python interesantes y potentes, ¡sigue leyendo!

Método 2: bucle for simple

El siguiente método es lo que verías de un programador procedente de otro lenguaje de programación o de un principiante que no conoce el operador de igualdad en las listas (consulta el Método 1).

#2. Simple For Loop
def method_2(l1, l2):
    for i in range(min(len(l1), len(l2))):
        if l1[i] != l2[i]:
            return False
    return len(l1) == len(l2)

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]
print(method_2(l1, l2))
# False

En el código, itera sobre todos los índices desde 0 hasta la última posición de la lista más pequeña según lo determinado por la parte min(len(l1), len(l2)). Luego, verifica si ambos elementos en la misma posición son diferentes. Si son diferentes, es decir, l1[i] != L2[i], puedes devolver False inmediatamente porque las listas también son diferentes.

Si pasó por todo el bucle sin devolver False, los elementos de la lista son similares. ¡Pero una lista aún puede ser más larga! Entonces, al devolver len(l1) == len(l2), te aseguras de devolver True sólo si (1) todos los elementos son iguales y (2) las listas tienen la misma longitud.

¡Mucho código para lograr algo tan simple! Veamos cómo un mejor programador aprovecharía la función zip() para reducir la complejidad del código.

Método 3: zip() + bucle for

La función zip toma varios iterables y los agrega en uno solo combinando los valores i-ésimos de cada iterable en una tupla para cada i.

Veamos cómo puedes usar la función para hacer que el código anterior sea más conciso:

# 3. Zip + For Loop
def method_3(l1, l2):
    for x, y in zip(l1, l2):
        if x != y:
            return False
    return len(l1) == len(l2)

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]
print(method_3(l1, l2))
# False


En lugar de iterar sobre índices, ahora iteras sobre pares de elementos (los que están comprimidos juntos). Si las listas tienen diferentes tamaños, se omitirán los elementos restantes de la lista más larga. De esta manera, la comparación por elementos se vuelve más simple y no se requieren esquemas de indexación complicados. ¡Evitar índices mediante la función zip() es una forma más pitónica sin duda!

Método 4: sum() + zip() + len()

Pero los verdaderos programadores de Python a menudo evitarán un bucle for y usarán una expresión generadora en su lugar.

  • Primero crea un iterable de valores booleanos usando la expresión del generador x == y for x, y in zip(l1, l2).
  • Luego, suma los valores booleanos (otro truco de los programadores profesionales) para encontrar el número de elementos que son iguales y almacenarlo en la variable num_equal.
  • Finalmente, lo comparas con la longitud de ambas listas. Si los tres valores son idénticos, ambas listas tienen los mismos elementos y su longitud también es la misma. ¡Son iguales!
# 4. Sum + Zip + Len
def method_4(l1, l2):
    num_equal = sum(x == y for x, y in zip(l1, l2))
    return num_equal == len(l1) == len(l2)

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]
print(method_4(l1, l2))
# False

print(method_4([1, 2], [1, 2]))
# True


De todos los métodos, excepto el primero que usa el operador ==, esta es la forma más pitónica debido al uso de funciones auxiliares de Python eficientes como zip(), len() y sum() y expresiones generadoras para hacer el código más conciso y más legible.

¡También puedes escribir esto en una sola línea de código!

sum(x == y for x, y in zip(l1, l2)) == len(l1) == len(l2)

Si te encanta el código de una línea de Python, echa un vistazo a mi nuevo libroPython One-Liners con la editorial de renombre internacional NoStarch Press. (Enlace a Amazon)

Método 5: map() + reduce() + len()

El último método es simplemente entrenar tus habilidades de programación funcional.

# 5. map() + reduce() + len()
from functools import reduce
def method_5(l1, l2):
    equal = map(lambda x, y: x == y, l1, l2)
    result = reduce(lambda x, y: x and y, equal)
    return result and len(l1) == len(l2)

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]
print(method_5(l1, l2))
# False

print(method_5([1, 2, 3], [1, 2, 3]))
# True


La función map()  combina todos los pares de elementos en valores booleanos (¿son iguales ambos elementos?). La función reduce() combina todos los valores booleanos realizando una operación and. Claro, también puedes usar la variante más concisa mediante la función all():

Método 6: map() + all()

Es lo mismo que el método anterior, pero usando la función all()  en lugar de reduce() para combinar todos los valores booleanos en una operación global and.

# 6. map() + all()
def method_6(l1, l2):
    result = all(map(lambda x, y: x == y, l1, l2))
    return result and len(l1) == len(l2)

l1 = [1, 2, 3, 4, 5]
l2 = [1, 2, 3]
print(method_5(l1, l2))
# False

print(method_5([1, 2, 3], [1, 2, 3]))
# True

Si deseas aprender algo nuevo todos los días, únete a mi serie gratuita de correos electrónicos de Python para una mejora continua en Python y ciencias de la computación.

Artículo original: La forma más pitónica de comprobar si dos listas ordenadas son idénticas

Diferencia

Respuesta corta: La forma más pitónica de calcular la diferencia entre dos listas l1 y l2 es la sentencia de comprensión de lista [x for x in l1 if x not in set(l2)]. Funciona incluso si tienes entradas de lista duplicadas, mantiene el orden de la lista original y es eficiente debido a la complejidad constante del tiempo de ejecución de la operación de pertenencia a un conjunto.

¿Cuál es la mejor manera de calcular la diferencia entre dos listas en Python?

a = [5, 4, 3, 2, 1]
b = [4, 5, 6, 7]

# a - b == [3, 2, 1]
# b - a == [6, 7]

Vamos a echarle un vistazo en el siguiente shell de código interactivo:

Ejercicio: ¡Ejecuta el código y piensa en tu forma preferida!

Profundicemos en cada uno de los métodos para encontrar el más pitónico para tu escenario concreto.

Método 1: diferencia de conjuntos

El enfoque cándido para resolver este problema es convertir ambas listas en conjuntos y usar la operación resta de conjuntos (o diferencia de conjuntos).

# Method 1: Set Difference
print(set(a) - set(b))
# {1, 2, 3}
print(set(b) - set(a))
# {6, 7}

Este enfoque es elegante porque es legible, eficiente y conciso.

Sin embargo, hay algunas características únicas de este método que debes conocer:

  • El resultado es un conjunto y no una lista. Puedes reconvertirlo en una lista utilizando el constructor list(…).
  • Todas las entradas duplicadas de la lista se eliminan en el proceso porque los conjuntos no pueden tener elementos duplicados.
  • El orden de la lista original se pierde porque los conjuntos no mantienen el orden de los elementos.

Si las tres características son aceptables para ti, este es, con mucho, el enfoque más eficiente, según se evalúa más adelante en este artículo

Sin embargo, ¿cómo se puede mantener el orden de los elementos de la lista original y al mismo tiempo permitir duplicados? ¡Vamos a sumergirnos en la alternativa de comprensión de listas!

Método 2: comprensión de listas

💡 La comprensión de listas es una forma compacta de crear listas. La fórmula simple es [expresión + contexto].

  • Expresión: ¿Qué hacer con cada elemento de la lista?
  • Contexto: ¿Qué elementos seleccionar? El contexto consta de un número arbitrario de declaraciones for e if.

Puedes usar la comprensión de listas para repasar cada elemento de la primera lista e ignorarlo si está en la segunda:

# Method 2: List Comprehension
print([x for x in a if x not in set(b)])
# [3, 2, 1]

Usamos la optimización pequeña pero efectiva de convertir primero la segunda lista b en un conjunto. La razón es que comprobar la pertenencia x in b es mucho más rápido para conjuntos que para listas. Sin embargo, semánticamente, ambas variantes son idénticas.

Estas son las propiedades distintivas de este enfoque:

  • El resultado de la declaración de comprensión de listas es una lista.
  • Se mantiene el orden de la lista original.
  • Se mantienen los elementos duplicados.

Si dependes de estas garantías más potentes, usa el enfoque de comprensión de listas porque es el más pitónico.

Método 3: bucle for simple

Sorprendentemente, algunos tutoriales en línea recomiendan usar un bucle for anidado (por ejemplo, esos tipos):

# Method 3: Nested For Loop
d = []
for x in a:
    if x not in b:
        d.append(x)
print(d)
# [3, 2, 1]

En mi opinión, este enfoque solo sería utilizado por principiantes absolutos o programadores que provienen de otros lenguajes de programación como C ++ o Java y no conocen las características esenciales de Python como la comprensión de listas. Puedes optimizar este método convirtiendo la lista b en un conjunto primero para acelerar la comprobación if x not in b por un amplio margen.

Artículo original: Diferencia de listas | La forma más pitónica

¿A dónde dirigirnos de aquí en adelante?

Suficiente teoría, ¡practiquemos un poco!

Para tener éxito en la codificación, debe salir y resolver problemas reales para personas reales. Así es como puede convertirse fácilmente en una fuente de ingresos de seis cifras. Y así es como perfeccionas las habilidades que realmente necesitas en la práctica. Después de todo, ¿de qué sirve la teoría del aprendizaje que nadie necesita?

¡Los proyectos de práctica son la forma de afilar su sierra en la codificación!

¿Quieres convertirte en un maestro del código enfocándote en proyectos de código prácticos que realmente te generen dinero y resuelvan problemas para las personas?

¡Entonces conviértete en un desarrollador autónomo de Python! Es la mejor manera de abordar la tarea de mejorar sus habilidades en Python, incluso si es un principiante total.

Únase a mi seminario web gratuito “Cómo desarrollar su pitón de habilidades de altos ingresos” y observe cómo crecí mi negocio de codificación en línea y cómo usted también puede hacerlo, desde la comodidad de su hogar.

¡Únase al webinar gratuito ahora!