Comment supprimer des éléments en double d'une liste à l'aide de la compréhension de la liste? J'ai suivi du code suivant: mais cela ne fonctionne pas, produit uniquement une liste identique. Pourquoi sa production d'une liste identique? P> p>
8 Réponses :
Si cela ne vous dérange pas d'utiliser une technique différente de la compréhension de la liste, vous pouvez utiliser un ensemble pour cela:
>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8] >>> b = list(set(a)) >>> print b [1, 2, 3, 5, 6, 7, 8, 9]
J'ai examiné la fonction définie, je veux simplement savoir ce qui ne va pas avec le code ci-dessus et si cela pourrait être corrigé?
ensemble ne gardera pas la commande initiale ... alors prenez notification de cela
@AdrioBan: que peut être corrigé avec des modifications de code minimes . Il est plus lent que d'utiliser Set code>, mais pas beaucoup i> plus lent si vous êtes sur 3,6+ (si vous êtes sur 3,5 et plus tôt en utilisant
ordonnancierddict code>, C'est un succès plus grand;> 3x Runtime, tandis que 3,6+ avec un clair
dict code> est seulement environ une augmentation de 66% du temps d'exécution).
Utilisez clés code> sur un
dict code> construit avec des valeurs dans
A code> comme clé.
b = [i for i in set(a)]
Il produit une liste identique comme B code> ne contient aucun élément au moment de l'exécution.
Ce que vous voudriez cela:
>>> a = [1, 2, 3, 3, 5, 9, 6, 2, 8, 5, 2, 3, 5, 7, 3, 5, 8]
>>> b = []
>>> [b.append(item) for item in a if item not in b]
[None, None, None, None, None, None, None, None]
>>> b
[1, 2, 3, 5, 9, 6, 8, 7]
Méfiez-vous d'utiliser compréhensions de liste pour les effets secondaires . Utilisez une boucle régulière à la place.
C'est aussi un O (n²) code> réponse, où, pour les entrées hachables,
o (n) code> est possible ( avec ou sans Préservation de la commande), et pour les entrées sans-frère, mais des entrées tricables,
O (n journal n) code> est possible (bien qu'il remplace la commande originale avec la commande triée, à moins que vous n'auriez pas accompli à décorer et d'indéterminer les entrées avec leur index et de l'intégrer dans le tri et la déduplication donc une seconde Trier peut restaurer la commande originale).
La raison pour laquelle la liste est inchangée est que B code> commence vide. Cela signifie que
si l'élément non in b code> est toujours
vrai code>. Ce n'est qu'après que la liste a été générée est cette nouvelle liste non vide attribuée à la variable
B code>. P>
Si je comprends bien, cela signifie que la compréhension de la liste ajoute des éléments à une option au lieu de vérifier et d'ajouter chaque élément à une heure comme en boucle.
@ALINWNDRLD: Je ne pense pas que ce soit une conclusion valable. Cela signifie seulement que la compréhension de la liste est évaluée avant l'affectation. La liste peut bien être construite dans une boucle en interne.
Utilisez Groupby :
>>> {k: len(list(v)) for k, v in groupby(sorted(a))} {1: 1, 2: 3, 3: 4, 5: 4, 6: 1, 7: 1, 8: 2, 9: 1}
>>> a = [10,20,30,20,10,50,60,40,80,50,40,0,100,30,60] >>> [a.pop(a.index(i, a.index(i)+1)) for i in a if a.count(i) > 1] >>> print(a)
>>> from itertools import groupby >>> repeated_items = [2,2,2,2,3,3,3,3,4,5,1,1,1] >>> [ ... next(group) ... for _, group in groupby( ... repeated_items, ... key=repeated_items.index ... ) ... ] [2, 3, 4, 5, 1]
Solution intelligente, j'aime bien. Inconvénient est l'appel code> index code>, ce qui le fait O (n²) code> et l'hypothèse que l'entrée est déjà regroupée (elle ne fonctionnera pas sur
[2, [2, 1,2] code>). Vous pouvez résoudre les deux problèmes, et i> préserver toujours l'ordre de saisie, avec une transformation Schwartzian modifiée (nécessite
à partir d'iTerTools Importer comptage, groupeby code>):
[v pour v, _ Dans Trié ([Suivant (GRP) pour _, GRP en Groupby (trié (zip (répété (répétid_items, comptage ())), clé = lambda x: x [0])], touche = lambda x: x [1])] code>. Pourrait ne pas valoir la peine, mais j'aime un bon bit de
iTertools code> Insanity alimenté.
Pour Python 3.6+, il y a une amélioration à avoir eu une amélioration de Niek de Klein's surtout excellente solution (c'est une faille principale être qu'il perd une commande de saisie). Étant donné que sur Python antérieur, vous feriez: p> dict code> s sont maintenant insertions-ordonnés, vous pouvez simplement faire:
from collections import OrderedDict
b = list(OrderedDict.fromkeys(a))
Parce que
B code> est vide pour le moment où vous exécutez
si l'élément n'est pas dans B code>. La compréhension de la liste est effectuée en mémoire et le résultat est attribué à
B code> à la fin.
Cela signifie que la compréhension de la liste ne fonctionne pas comme une boucle?
Si vous ne voulez pas utiliser un ensemble, car vous souhaitez conserver la commande, consultez le
unique_everseen code> itérateur dans le ITERTOOLS Recettes . Utilisez comme ceci:
b = liste (unique_everseen (a)) code>
C'est une sorte de boucle, mais cela génère le résultat en une fois ... ce n'est pas si surprenant non plus. Chaque fois que vous avez l'expression
x = y code>, alors
y code> est évalué d'abord, puis le résultat est attribué à
x code>. Mais pendant l'évaluation de
y code>,
x code> n'est pas modifié. Auriez-vous eu les mêmes doutes si vous aviez
B = liste (élément pour l'élément dans un élément IF non in b) code> à la place?