web-dev-qa-db-fra.com

Supprimer toutes les valeurs d'une liste d'une autre liste?

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]  
106
ariel
>>> a = range(1, 10)
>>> [x for x in a if x not in [2, 3, 7]]
[1, 4, 5, 6, 8, 9]
122
YOU

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.

44
arunjitsingh

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!

39
The Godfather
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.

25
Yaroslav

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]
7
John La Rooy

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.

6
Anurag Uniyal
>>> 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]
5
ghostdog74