Disons que j'ai deux listes, l1
et l2
. Je veux effectuer l1 - l2
, qui renvoie tous les éléments de l1
pas dans l2
.
Je peux penser à une approche en boucle naïve pour faire cela, mais cela va être vraiment inefficace. Qu'est-ce qu'un moyen pythonique et efficace de le faire?
Par exemple, si je dois l1 = [1,2,6,8] and l2 = [2,3,5,8]
, l1 - l2
devrait revenir[1,6]
Réponses:
Python a une fonctionnalité de langage appelée List Comprehensions qui est parfaitement adaptée pour rendre ce genre de chose extrêmement facile. L'instruction suivante fait exactement ce que vous voulez et stocke le résultat dans
l3
:l3
contiendra[1, 6]
.la source
in
opérateur n'est pas aussi efficace sur une liste.in
sur une liste est O (n), tandis quein
sur un ensemble est O (1). Cependant, jusqu'à ce que vous atteigniez des milliers d'éléments ou plus, vous ne remarquerez probablement pas la différence.l3 = [x for x in l1 if x not in set(l2)]
? Je suis sûr queset(l2)
serait appelé plus d'une fois.l2s = set(l2)
puis direl3 = [x for x in l1 if x not in l2s]
. Un peu plus facile.Une façon consiste à utiliser des ensembles:
la source
l1
, ce qui peut être un effet secondaire indésirable.timeit.timeit('a = [1,2,3,4]; b = [1,3]; c = [i for i in a if a not in b]', number=100000) -> 0.12061533199999985
timeit.timeit('a = {1,2,3,4}; b = {1,3}; c = a - b', number=100000) -> 0.04106225999998969
. Donc, si les performances sont un facteur important, cette réponse peut être plus appropriée (et aussi si vous ne vous souciez pas des doublons ou de la commande)Comme alternative, vous pouvez également utiliser
filter
avec l'expression lambda pour obtenir le résultat souhaité. Par exemple:Comparaison des performances
Ici, je compare les performances de toutes les réponses mentionnées ici. Comme prévu, l'
set
opération basée sur Arkku est la plus rapide.Arkku's Set Difference - First (0,124 usec par boucle)
Compréhension de liste de Daniel Pryden avec
set
recherche - Deuxième (0,302 usec par boucle)Compréhension de la liste de Donut sur liste simple - Troisième (0,552 usec par boucle)
Utilisation de Moinuddin Quadri
filter
- Quatrième (0,972 usec par boucle)Akshay Hazari utilise une combinaison de
reduce
+filter
- Cinquième (3,97 usec par boucle)PS:
set
ne conserve pas l'ordre et supprime les éléments en double de la liste. Par conséquent, n'utilisez pas la différence définie si vous en avez besoin.la source
En développant la réponse de Donut et les autres réponses ici, vous pouvez obtenir des résultats encore meilleurs en utilisant une compréhension de générateur au lieu d'une compréhension de liste et en utilisant une
set
structure de données (puisque lein
opérateur est O (n) sur une liste mais O (1) sur un ensemble).Voici donc une fonction qui fonctionnerait pour vous:
Le résultat sera un itérable qui récupérera paresseusement la liste filtrée. Si vous avez besoin d'un véritable objet liste (par exemple, si vous devez faire un
len()
résultat), vous pouvez facilement créer une liste comme ceci:la source
Utilisez le type d'ensemble Python. Ce serait le plus pythonique. :)
De plus, comme il est natif, il devrait également être la méthode la plus optimisée.
Voir:
http://docs.python.org/library/stdtypes.html#set
http://docs.python.org/library/sets.htm (pour les anciens python)
la source
l1
comprend des éléments répétés.utilisez Set Comprehensions {x pour x dans l2} ou set (l2) pour obtenir l'ensemble, puis utilisez List Comprehensions pour obtenir la liste
code de test de référence:
résultat du test de référence:
la source
l2set = set( l2 )
au lieu del2set = { x for x in l2 }
Solution alternative:
la source