Python >> Tutoriel Python >  >> Python

La manière la plus pythonique de comparer deux listes en Python

Problème :Soit deux listes l1 et l2 . Vous souhaitez effectuer l'une des actions suivantes :

  • 1. Comparaison booléenne :Compare les listes élément par élément et renvoie True si votre métrique de comparaison renvoie True pour toutes les paires d'éléments, et sinon False .
  • 2. Différence :Trouver la différence des éléments dans la première liste mais pas dans la seconde.

Exemple :Vous commencez avec deux listes.

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

# 1. Boolean Comparison
result = False

# 2. Difference
result = [4, 5]

Discutons des moyens les plus Pythoniques d'accomplir ces problèmes. Nous commençons par cinq façons d'effectuer la comparaison booléenne et examinons ensuite cinq façons d'effectuer la différence simple.

Comparaison booléenne

Réponse courte : La façon la plus Pythonique de vérifier si deux listes ordonnées l1 et l2 sont identiques, est d'utiliser le l1 == l2 opérateur de comparaison élément par élément. Si tous les éléments sont égaux et que la longueur des listes est la même, la valeur de retour est True .

Problème :Soit deux listes l1 et l2 . Vous souhaitez effectuer une comparaison booléenne :Compare les listes élément par élément et renvoie True si votre métrique de comparaison renvoie True pour toutes les paires d'éléments, et sinon False .

Exemples :

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

Discutons des moyens les plus Pythoniques de résoudre ce problème. Voici un bref aperçu interactif du code :

Exercice :Jetez un coup d'œil sur toutes les méthodes et exécutez le code. Quelles questions vous viennent à l'esprit ? Comprenez-vous chaque méthode ?

Lisez la suite pour en savoir plus sur chaque méthode en détail !

Méthode 1 :comparaison simple

La méthode la plus simple n'est pas toujours la meilleure. Mais pour ce problème particulier, ça l'est ! L'opérateur d'égalité == compare une liste élément par élément - de nombreux codeurs Python ne le savent pas !

# 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

Donc, si vous voulez simplement en savoir plus sur la manière la plus Pythonique de résoudre ce problème, ne cherchez pas plus loin.

Mais si vous voulez plonger dans le monde merveilleux de Python et découvrir différentes fonctions Python intéressantes et puissantes, lisez la suite !

Méthode 2 :boucle for simple

La méthode suivante est ce que vous verriez d'un codeur venant d'un autre langage de programmation ou d'un débutant qui ne connaît pas l'opérateur d'égalité sur les listes (voir Méthode 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

Dans le code, vous parcourez tous les indices de 0 à la dernière position de la plus petite liste comme déterminé par la partie min(len(l1), len(l2)) . Vous vérifiez ensuite si les deux éléments à la même position sont différents. S'ils sont différents, c'est-à-dire l1[i] != l2[i] , vous pouvez retourner immédiatement False car les listes sont également différentes.

Si vous avez parcouru toute la boucle sans retourner False , les éléments de la liste sont similaires. Mais une liste peut encore être plus longue ! Donc, en retournant len(l1) == len(l2) , vous vous assurez de ne renvoyer que True si (1) tous les éléments sont égaux et (2) les listes ont la même longueur.

Beaucoup de code pour accomplir une chose aussi simple ! Voyons comment un meilleur codeur tirerait parti du zip() fonction pour réduire la complexité du code.

Méthode 3 :zip() + boucle For

La fonction zip prend un certain nombre d'itérables et les agrège en un seul en combinant les ièmes valeurs de chaque itérable en un tuple pour chaque i.

Voyons comment vous pouvez utiliser la fonction pour rendre le code précédent plus concis :

# 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

Au lieu d'itérer sur les index, vous itérez maintenant sur des paires d'éléments (ceux compressés ensemble). Si les listes ont des tailles différentes, les éléments restants de la liste plus longue seront ignorés. De cette façon, la comparaison élément par élément devient plus simple et aucun schéma d'indexation élaboré n'est requis. Éviter les indices au moyen du zip() la fonction est une manière plus Pythonique à coup sûr !

Méthode 4 :somme() + zip() + len()

Mais les vrais codeurs Python éviteront souvent une boucle for et utiliseront une expression de générateur à la place.

  • Vous créez d'abord un itérable de valeurs booléennes à l'aide de l'expression de générateur x == y for x, y in zip(l1, l2) .
  • Ensuite, vous additionnez les valeurs booléennes (une autre astuce des codeurs professionnels) pour trouver le nombre d'éléments qui sont identiques et le stockez dans la variable num_equal .
  • Enfin, vous comparez cela avec la longueur des deux listes. Si les trois valeurs sont identiques, les deux listes ont les mêmes éléments et leur longueur est également la même. Ils sont égaux !
# 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

Parmi les méthodes sauf la première utilisant le == opérateur, c'est le moyen le plus Pythonique en raison de l'utilisation de fonctions d'assistance Python efficaces comme zip(), len(), and sum() et des expressions génératrices pour rendre le code plus concis et plus lisible.

Vous pouvez également l'écrire en une seule ligne de code !

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

Si vous aimez les one-liners Python, consultez mon nouveau livre Python One-Liners avec l'éditeur de renommée internationale NoStarch press. (Lien Amazon)

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

La dernière méthode consiste simplement à former vos compétences en programmation fonctionnelle.

# 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

Le map() La fonction combine toutes les paires d'éléments en valeurs booléennes (les deux éléments sont-ils égaux ?). Le reduce() la fonction combine toutes les valeurs booléennes en effectuant un and opération. Bien sûr, vous pouvez également utiliser la variante plus concise en utilisant le all() fonction :

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

C'est la même chose que la méthode précédente, mais en utilisant le all() fonction au lieu de reduce() pour combiner toutes les valeurs booléennes dans un ensemble et global opération.

# 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 vous voulez apprendre quelque chose de nouveau chaque jour, rejoignez ma série d'e-mails Python gratuits pour une amélioration continue de Python et de l'informatique.

Article d'origine : La façon la plus pythonique de vérifier si deux listes ordonnées sont identiques

Différence

Réponse courte :La manière la plus Pythonique de calculer la différence entre deux listes l1 et l2 est la déclaration de compréhension de liste [x for x in l1 if x not in set(l2)] . Cela fonctionne même si vous avez des entrées de liste en double, cela maintient l'ordre de liste d'origine et c'est efficace en raison de la complexité d'exécution constante de l'opération d'appartenance définie.

Quelle est la meilleure façon de calculer la différence entre deux listes en Python ?

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

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

Ayons un aperçu dans le shell de code interactif suivant :

Exercice  :Exécutez le code et réfléchissez à votre méthode préférée !

Plongeons-nous dans chacune des méthodes pour trouver celle qui convient le mieux à votre scénario particulier.

Méthode 1 :Définir la différence

L'approche naïve pour résoudre ce problème consiste à convertir les deux listes en ensembles et à utiliser l'opération ensemble moins (ou ensemble différence).

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

Cette approche est élégante car elle est lisible, efficace et concise.

Cependant, cette méthode possède certaines propriétés uniques dont vous devez être conscient :

  • Le résultat est un ensemble et non une liste. Vous pouvez le reconvertir en liste en utilisant le list(...) constructeur.
  • Toutes les entrées de liste en double sont supprimées dans le processus car les ensembles ne peuvent pas avoir d'éléments en double.
  • L'ordre de la liste d'origine est perdu car les ensembles ne conservent pas l'ordre des éléments.

Si les trois propriétés vous conviennent, c'est de loin l'approche la plus efficace telle qu'évaluée plus loin dans cet article !

Cependant, comment pouvez-vous conserver l'ordre des éléments de la liste d'origine tout en autorisant les doublons ? Plongeons-nous dans la compréhension de la liste alternative !

Méthode 2 :Compréhension de la liste

La compréhension de liste est une manière compacte de créer des listes. La formule simple est [expression + context] .

  • Expression :Que faire de chaque élément de la liste ?
  • Contexte :Quels éléments sélectionner ? Le contexte consiste en un nombre arbitraire de for et if déclarations.

Vous pouvez utiliser la compréhension de liste pour passer en revue tous les éléments de la première liste, mais les ignorer s'ils se trouvent dans la seconde liste :

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

Nous avons utilisé une optimisation petite mais efficace pour convertir la deuxième liste b à un ensemble d'abord. La raison en est que la vérification de l'appartenance x in b est beaucoup plus rapide pour les ensembles que pour les listes. Cependant, sémantiquement, les deux variantes sont identiques.

Voici les propriétés distinctives de cette approche :

  • Le résultat de la déclaration de compréhension de liste est une liste.
  • L'ordre de la liste d'origine est conservé.
  • Les éléments en double sont conservés.

Si vous comptez sur ces garanties plus puissantes, utilisez l'approche de compréhension de liste car c'est la plus Pythonique.

Méthode 3 :boucle for simple

Étonnamment, certains tutoriels en ligne recommandent d'utiliser une boucle for imbriquée (par exemple, ces gars-là) :

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

À mon avis, cette approche ne serait utilisée que par des débutants absolus ou des codeurs qui viennent d'autres langages de programmation tels que C++ ou Java et ne connaissent pas les fonctionnalités Python essentielles comme la list comprehension . Vous pouvez optimiser cette méthode en convertissant la liste b à un ensemble d'abord pour accélérer la vérification if x not in b par une marge non négligeable.

Article d'origine :Différence de liste | La manière la plus pythonique