Je cherche un moyen de supprimer toutes les valeurs d'une liste d'une autre liste.
Quelque chose comme ça:
a = range(1,10)
a.remove([2,3,7])
print a
a = [1,4,5,6,8,9]
>>> a = range(1, 10)
>>> [x for x in a if x not in [2, 3, 7]]
[1, 4, 5, 6, 8, 9]
Si vous n'avez pas de valeurs répétées, vous pouvez utiliser la différence définie.
x = set(range(10))
y = x - set([2, 3, 7])
# y = set([0, 1, 4, 5, 6, 8, 9])
puis reconvertissez à la liste, si nécessaire.
Je cherchais un moyen rapide de faire le sujet, alors j’ai fait quelques expériences avec des moyens suggérés. Et j'ai été surpris par les résultats, alors je veux le partager avec vous.
Les expériences ont été effectuées à l'aide de l'outil pythonbenchmark et avec
a = range(1,50000) # Source list
b = range(1,15000) # Items to remove
Résultats:
def comprehension(a, b):
return [x for x in a if x not in b]
5 essais, temps moyen 12.8 sec
def filter_function(a, b):
return filter(lambda x: x not in b, a)
5 essais, temps moyen 12.6 sec
def modification(a,b):
for x in b:
try:
a.remove(x)
except ValueError:
pass
return a
5 essais, temps moyen 0.27 sec
def set_approach(a,b):
return list(set(a)-set(b))
5 essais, temps moyen ,0057 sec
J'ai aussi fait une autre mesure avec une taille d'entrée plus grande pour les deux dernières fonctions
a = range(1,500000)
b = range(1,100000)
Et les résultats:
Pour modification (supprimer la méthode) - le temps moyen est de 252 secondes Pour l'approche définie - le temps moyen est de ,75 secondes
Vous pouvez donc voir que cette approche avec les ensembles est considérablement beaucoup plus rapidement que d’autres. Oui, il ne conserve pas les mêmes objets, mais si vous n'en avez pas besoin, c'est pour vous. Et il n'y a presque pas de différence entre la compréhension de liste et l'utilisation de la fonction de filtrage. Utiliser 'remove' est environ 50 fois plus rapide, mais cela modifie la liste des sources. Et le meilleur choix est d'utiliser des ensembles - c'est plus de 1000 fois plus rapide que la compréhension de liste!
a = range(1,10)
itemsToRemove = set([2, 3, 7])
b = filter(lambda x: x not in itemsToRemove, a)
ou
b = [x for x in a if x not in itemsToRemove]
Ne créez pas l'ensemble à l'intérieur de lambda
ou à l'intérieur de la compréhension. Si vous le faites, il sera recréé à chaque itération, annulant ainsi le point d'utiliser un ensemble.
Le plus simple est
>>> a = range(1, 10)
>>> for x in [2, 3, 7]:
... a.remove(x)
...
>>> a
[1, 4, 5, 6, 8, 9]
Un problème possible ici est que chaque fois que vous appelez remove (), tous les éléments sont mélangés dans la liste pour combler le trou. Donc, si a
devient très volumineux, cela finira par être assez lent.
De cette façon, construit une nouvelle liste. L’avantage est que nous évitons tout remaniement de la première approche
>>> removeset = set([2, 3, 7])
>>> a = [x for x in a if x not in removeset]
Si vous souhaitez modifier a
à la place, une seule petite modification est nécessaire.
>>> removeset = set([2, 3, 7])
>>> a[:] = [x for x in a if x not in removeset]
D'autres ont suggéré des moyens de créer une nouvelle liste après avoir filtré, par exemple.
newl = [x for x in l if x not in [2,3,7]]
ou
newl = filter(lambda x: x not in [2,3,7], l)
mais à partir de votre question, il semble que vous souhaitiez une modification sur place pour pouvoir le faire, cela sera également beaucoup plus rapide si la liste d'origine est longue et si les éléments doivent être supprimés moins
l = range(1,10)
for o in set([2,3,7,11]):
try:
l.remove(o)
except ValueError:
pass
print l
sortie: [1, 4, 5, 6, 8, 9]
Je vérifie l'exception ValueError afin que cela fonctionne même si les éléments ne sont pas dans la liste originale.
Aussi, si vous n'avez pas besoin de la solution de modification sur place de S.Mark
est plus simple.
>>> a=range(1,10)
>>> for i in [2,3,7]: a.remove(i)
...
>>> a
[1, 4, 5, 6, 8, 9]
>>> a=range(1,10)
>>> b=map(a.remove,[2,3,7])
>>> a
[1, 4, 5, 6, 8, 9]