List Manipulation en Python avec pop ()
En bref, j'ai besoin de supprimer plusieurs éléments d'une liste en fonction de leur index. Cependant, je ne peux pas utiliser de la pop, car il met l'index (sans quelques maladroit de compensation du système). Est-il un moyen de supprimer plusieurs éléments en même temps?
J'ai un algorithme qui parcourt la liste, et si les conditions sont réunies supprime cet élément via le menu de la méthode. Un problème se pose vu que c'est fait dans une boucle. Une fois que pop est en fait la liste est raccourcie par un, le déplacement de toutes les valeurs de un. Donc la boucle va sortir de la plage. Il est possible de supprimer plusieurs éléments simultanément, ou une autre solution?
Un exemple de mon problème:
L = ['a', 'b', 'c', 'd']
for i in range(len(L)):
print L
if L[i] == 'a' or L[i] == 'c':
L.pop(i)
source d'informationauteur rectangletangle
Vous devez vous connecter pour publier un commentaire.
Sont vos listes? Si oui, utiliser
ifilter
deitertools
pour filtrer les éléments que vous ne voulez pas paresseusement (pas de coût d'achat).Listes pas si grand? Il suffit d'utiliser une compréhension de liste:
Cela va créer une nouvelle copie de la liste. Ce n'est généralement pas un problème pour l'efficacité, à moins que vous vous souciez vraiment de la consommation de mémoire.
Comme un heureux moyen de la syntaxe de la commodité et de la paresse ( = efficacité pour les grandes listes), vous pouvez construire un générateur plutôt que d'une liste à l'aide de
(
)
au lieu de[
]
:Après cela, vous pouvez effectuer une itération sur
interestingelts
mais vous ne pouvez pas l'index:Vous voulez une compréhension de liste:
Ou, si vous ne voulez vraiment pas à créer une copie, revenir en arrière:
Grâce à ncoghlan pour
reversed()
& phooji pourdel L[i]
suggestions. (J'ai décidé de la laisserL.pop(i)
puisque c'est la façon dont la question a été initialement formulée.)Aussi, comme J. S. Sébastien justement, en allant vers l'arrière est efficace de l'espace mais le temps inefficace; la plupart du temps une compréhension de liste ou d'un générateur (
L = (...)
au lieu deL = [...]
) est le meilleur.Edit:
Ok, donc, puisque les gens semblent vouloir quelque chose de moins ridiculement lent que l'inversion de la méthode ci-dessus (je ne peux pas imaginer pourquoi... 🙂 voici un ordre de préservation de la, en place un filtre qui doit différer de la vitesse à partir d'une compréhension de liste uniquement par une constante. (Cela rejoint ce que je ferais si je le voulais pour filtrer une chaîne de caractères en c.)
Sommaire
str.translate()
pour supprimer des caractèresdel L[i]
est lente pour les grandes listesSi des éléments sont octets comme dans votre exemple, vous pourriez utiliser
str.translate()
:En général plusieurs éléments pourraient être supprimés à l'aide de découpage:
Comme @phooji et @senderle déjà mentionné compréhension de liste (ou générateur d'expression) est préférable dans votre cas:
Voici une comparaison des performances pour les
L=list("abcd"*10**5); delitems="ac"
:Où
remove_inplace_senderle()
est lente à cause qu'il utiliseO(N**2)
algorithme. Chaquedel L[i]
pourrait causer tous les éléments à droite à être déplacé de gauche à combler l'écart.Le temps de colonne dans le tableau ci-dessus inclut le temps qu'il faut pour créer une nouvelle liste d'entrée (la première ligne) en raison de certains algorithmes de modifier une entrée directe.
Voici les horaires pour la même entrée, mais sans créer une nouvelle liste à chaque itération:
Le tableau montre que
itertools.ifilterfalse()
ne pas fournir une amélioration significative de plus de listcomp.En général, il n'est pas la peine, ou même nuisible à réfléchir sur la performance pour de telles tâches, à moins d'un profileur prouvé que ce code est un goulot d'étranglement, et il est important pour votre programme. Mais il pourrait être utile d'être au courant des solutions de rechange qui pourraient fournir de plus d'un ordre de grandeur amélioration de la vitesse.