2010-08-18 19 views
9

Désolé si la question est peu confuse. Ceci est similaire à this questionComment faire pour supprimer la liste des mots d'une liste de chaînes

Je pense que la question ci-dessus est proche de ce que je veux, mais dans Clojure.

Il est another question

je besoin de quelque chose comme ça, mais au lieu de « [br] » dans cette question, il y a une liste de chaînes qui doivent rechercher et supprimées. J'espère que je me suis fait comprendre.

Je pense que cela est dû au fait que les chaînes en python sont immuables.

J'ai une liste de mots parasites qui doivent être supprimés d'une liste de chaînes.

Si j'utilise la compréhension de liste, je finis par rechercher la même chaîne encore et encore. Ainsi, seul "de" est retiré et non "le". Donc, ma liste modifiée ressemble à ceci

places = ['New York', 'the New York City', 'at Moscow' and many more] 

noise_words_list = ['of', 'the', 'in', 'for', 'at'] 

for place in places: 
    stuff = [place.replace(w, "").strip() for w in noise_words_list if place.startswith(w)] 

Je voudrais savoir quelle erreur je fais.

+1

Qu'est-ce 'place'? – katrielalex

+0

Vous ne vous faites pas clair; énoncez votre question * ici *, puis mettez des liens vers des questions similaires avec des réponses similaires si vous pensez que cela est nécessaire ci-dessous. –

Répondre

9

Voici mon coup de poignard. Cela utilise des expressions régulières.

import re 
pattern = re.compile("(of|the|in|for|at)\W", re.I) 
phrases = ['of New York', 'of the New York'] 
map(lambda phrase: pattern.sub("", phrase), phrases) # ['New York', 'New York'] 

Sans lambda:

[pattern.sub("", phrase) for phrase in phrases] 

Mise à jour

Fix pour le bug signalé par gnibbler (merci!):

pattern = re.compile("\\b(of|the|in|for|at)\\W", re.I) 
phrases = ['of New York', 'of the New York', 'Spain has rain'] 
[pattern.sub("", phrase) for phrase in phrases] # ['New York', 'New York', 'Spain has rain'] 

@prabhu: le changement ci-dessus évite d'arracher le fin "dans "de" Espagne ". Pour vérifier exécuter les deux versions des expressions régulières contre la phrase "l'Espagne a la pluie".

+0

Merci. Cela fonctionne de cette façon. J'ai été en mesure de mieux comprendre le concept de lambda maintenant que j'ai eu l'occasion de le mettre en œuvre. – prabhu

+1

Cela ne fonctionne pas correctement pour la phrase "L'Espagne a de la pluie". Il est facile de corriger si –

+0

@Gnibbler: merci de le signaler. Je change ma réponse en conséquence. –

3
>>> import re 
>>> noise_words_list = ['of', 'the', 'in', 'for', 'at'] 
>>> phrases = ['of New York', 'of the New York'] 
>>> noise_re = re.compile('\\b(%s)\\W'%('|'.join(map(re.escape,noise_words_list))),re.I) 
>>> [noise_re.sub('',p) for p in phrases] 
['New York', 'New York'] 
+0

Wow! C'est une façon vraiment cool de faire, même si j'ai épuisé mon cerveau. :-) – prabhu

+0

Cela ne semble pas obtenir tous les exemples de mots. Par exemple, "de New York de" devient "New York de". – Namey

+1

@ Namey, vous pourriez utiliser quelque chose comme \\ W \ \ \ \ (% s) \\ W? ''. Sans l'OP fournissant un ensemble complet de testcases, c'est un peu un whack-a-mole –

1

Puisque vous voulez savoir ce que vous faites mal, cette ligne:

stuff = [place.replace(w, "").strip() for w in noise_words_list if place.startswith(w)] 

a lieu, puis commence à boucle sur les mots. D'abord, il vérifie "de". Votre place (par exemple "du New York") est vérifiée pour voir si elle commence par "de". Il est transformé (appel à remplacer et dénuder) et ajouté à la liste des résultats. La chose cruciale ici est que le résultat n'est jamais examiné à nouveau. Pour chaque mot que vous itérez dans la compréhension, un nouveau résultat est ajouté à la liste des résultats. Donc le mot suivant est "le" et votre place ("du New York") ne commence pas par "le", donc aucun nouveau résultat n'est ajouté.

Je suppose que le résultat que vous avez finalement est la concaténation de vos variables de lieu. Une plus simple à lire et à comprendre la version procédurale serait (non testé):

results = [] 
for place in places: 
    for word in words: 
     if place.startswith(word): 
      place = place.replace(word, "").strip() 
    results.append(place) 

Gardez à l'esprit que replace() va supprimer le mot partout dans la chaîne, même si elle se produit comme une sous-chaîne simple. Vous pouvez éviter cela en utilisant regexes avec un modèle quelque chose comme ^the\b.

+0

Merci. C'était très utile. – prabhu

14

Sans regexp vous pourriez faire comme ceci:

places = ['of New York', 'of the New York'] 

noise_words_set = {'of', 'the', 'at', 'for', 'in'} 
stuff = [' '.join(w for w in place.split() if w.lower() not in noise_words_set) 
     for place in places 
     ] 
print stuff 
+0

Excellent! Je vous remercie! – prabhu

+0

Je suis tombé sur cela et je n'avais aucune idée de ce qui se passait ici. Si quelqu'un trébuche à travers cela et se demande ce qu'est la magie, c'est ce qu'on appelle la compréhension de la liste et c'est un bon article qui l'explique http://carlgroner.me/Python/2011/11/09/An-Introduction-to-List-Comprehensions- in-Python.html –