2017-08-28 1 views
0

J'ai une grande liste qui ressemble à ceci:Suppression d'éléments d'une liste qui manquent certaines chaînes - python

entries = ["['stuff']...other stuff", "['stuff']...stuff", "['stuff']...more stuff", ...] 

Je veux supprimer tous les éléments de la liste qui ne le font pas contiennent les mots "autre" ou "choses".

J'ai essayé, mais il ne supprime pas tous les éléments dont j'ai besoin pour (seulement quelques-uns à la fin):

for e in entries: 
    if 'other' or 'things' not in e: 
     entries.remove(e) 
print entries 

Qu'est-ce que je fais mal?

+0

En outre, notez, [ceci] (https://stackoverflow.com/questions/1157106/remove-all-occurrences-of-a-value-from-a-list) sera votre prochain bug ... –

+0

Qui a rouvert ça? Ceci est ** clairement un doublon ** de [ceci] (https://stackoverflow.com/questions/15112125/how-do-i-test-one-variable-against-multiple-values) –

Répondre

1

Vous ne devez pas supprimer des éléments d'une liste pendant leur itération. En outre, votre instruction conditionnelle ne fait pas ce que vous voulez dire: elle vérifie 'other' pour la véracité et seulement 'things' pour le confinement. Pour le résoudre, utilisez and avec deux vérifications in distinctes.

Si la liste est pas très grand, vous pouvez simplement utiliser une compréhension de la liste pour le reconstruire:

entries = [e for e in entries if "other" not in e and "things" not in e] 

Sinon, la boucle de la fin de la liste au début et supprimer des éléments par index.

for i in range(len(entries)-1, -1, -1): 
    if "other" in entries[i] and "things" in entries[i]: 
     del entries[i] 
+1

Eh bien, les deux sont assez gros problèmes. Mais la cause proximale de la question est le conditionnel. Et suivi de près sera la modification de la liste au cours de l'itération. Pour l'anecdote, je n'ai pas downvote ... –

0

Comme d'autres l'ont déjà souligné, dans votre version, il y a trois problèmes principaux:

for e in entries: 
    if 'other' or 'things' not in e: #or returns first truthy value, and `if other` is always true. Also, you need and, not or. 
     entries.remove(e) #mutating the item you are iterating over is bad 
print entries 

Voici votre version révisée pour résoudre les problèmes ci-dessus:

for e in words[:]: #words[:] is a copy of words, solves mutation issue while iterating 
    if 'other' not in e and 'things' not in e: #want words that both don't contain 'other' AND dont contain 'things' 
     print(e) 
     words.remove(e) 
print(words) 

Et Voici d'autres façons de le faire:

import re 

words = ['this doesnt contain chars you want so gone', 
     'this contains other so will be included', 
     'this is included bc stuff'] 

answer = list(filter(lambda x: re.search('other|stuff',x),words)) 
other_way = [sentence for sentence in words if re.search('other|stuff',sentence)] 

print(answer) 
print(other_way) 
+0

soin d'expliquer le downvote? – Solaxun

+0

Je n'ai pas downvote, mais cette réponse est de mauvaise qualité. Il fournit simplement une méthode alternative, avec * aucune explication * de la raison pour laquelle la méthode originale était erronée, ou comment vos alternatives fonctionnent réellement, et si la question concerne les conditions de base, alors cela ne sera pas très utile. –

0

Vous peut utiliser l'expression de la compréhension de la liste à l'aide all(..) pour vérifier la sous-chaîne:

>>> [entry for entry in entries if any(something in entry for something in ["other", "things"])] 

Cela vous ramènera la nouvelle liste de mots contenant soit « autre » ou « choses ».