2014-09-02 19 views
7

Nehmen wir an, ich den folgenden Satz haben:Ersetzen Sie alle Vorkommen von bestimmten Wörtern

bean likes to sell his beans 

und ich möchte alle Vorkommen bestimmter Wörter mit anderen Worten ersetzen. Zum Beispiel bean bis robert und beans bis cars.

Ich kann nicht einfach str.replace verwenden, weil in diesem Fall die beans zu roberts geändert wird.

>>> "bean likes to sell his beans".replace("bean","robert") 
'robert likes to sell his roberts' 

Ich muss nur die ganzen Wörter ändern, nicht die Vorkommen des Wortes in dem anderen Wort. Ich denke, dass ich dies erreichen kann, indem ich reguläre Ausdrücke verwende, aber ich weiß nicht, wie ich das richtig machen soll.

+0

Sie könnten 'split()' die der Text in Worte zuerst – cmd

Antwort

14

Wenn Sie Regex verwenden, können Sie Wortgrenzen mit \b angeben 'Am Ende ist keine Grenze zwischen Wörtern: \b entspricht der leeren Zeichenfolge, aber nur am Anfang oder Ende eines Wortes.

Der zweite Ersatz der Vollständigkeit halber:

sentence = re.sub(r'\bbeans\b', 'cars', sentence) 
# 'robert likes to sell his cars' 
+1

Warum die Klammern? – Jerry

+1

Ich nehme an, die Klammern sind nicht notwendig, sie haben nur die Regex lesbarer gemacht (zumindest für mich). –

+0

Aus irgendeinem Grund scheint dies nicht alle Vorkommen von US – Kahless

-1
"bean likes to sell his beans".replace("beans", "cars").replace("bean", "robert") 

Ersetzt alle Instanzen von "Bohnen" durch "Autos" und "Bohnen" durch "Robert". Dies funktioniert, weil .replace() eine modifizierte Instanz der ursprünglichen Zeichenfolge zurückgibt. Als solches können Sie in Stufen denken. Es funktioniert im Wesentlichen so aus:

import re 

sentence = 'bean likes to sell his beans' 

sentence = re.sub(r'\bbean\b', 'robert', sentence) 
# 'robert likes to sell his beans' 

Hier Bohnen 'nicht geändert werden (zu 'robert'), weil die ‚s:

>>> first_string = "bean likes to sell his beans" 
>>> second_string = first_string.replace("beans", "cars") 
>>> third_string = second_string.replace("bean", "robert") 
>>> print(first_string, second_string, third_string) 

('bean likes to sell his beans', 'bean likes to sell his cars', 
    'robert likes to sell his cars') 
+0

ich es nicht auf diese Weise in Echt Aufgabe tun, weil die Reihenfolge der diese Ersetzungen nicht definiert ist – FrozenHeart

3

Wenn Sie jedes Wort auf einmal ersetzen, könnte man Worte mehrmals ersetzen (und nicht das bekommen, was Sie wollen). Um dies zu vermeiden, können Sie eine Funktion oder Lambda verwenden:

d = {'bean':'robert', 'beans':'cars'} 
str_in = 'bean likes to sell his beans' 
str_out = re.sub(r'\b(\w+)\b', lambda m:d.get(m.group(1), m.group(1)), str_in) 

Auf diese Weise einmal bean durch robert ersetzt wird, es wird nicht wieder geändert werden (auch wenn robert ist auch in Ihrer Eingabe Wortliste). Wie von georg vorgeschlagen, habe ich diese Antwort mit bearbeitet. Alternative Lösung (auch von georg vorgeschlagen):

str_out = re.sub(r'\b(%s)\b' % '|'.join(d.keys()), lambda m:d.get(m.group(1), m.group(1)), str_in) 
+0

zu bekommen. Sie sollten in der Lage sein, das einfacher (und schneller) zu machen und das 'if' zu entfernen, um direkt in das dict zu schauen, wenn Sie' \ bbeans? \ B' dafür verwenden regex und benutze 'm.group (0)' (für das ganze Spiel) im Lambda. – Jerry

+0

Ich möchte, dass dies allgemein genug ist, so dass 1 Regex mit jedem Eingabetext und jeder Liste von Wörtern umgehen kann, die ersetzt werden sollen. Also ich will keine "Bohnen" in meiner Regex. – seb

+0

Ich verstehe. Es ist nur, dass es jedes einzelne Wort prüft und ich glaube, das ist der größte Engpass. – Jerry

-1

ich seine seit kenne eine lange Zeit, aber Enthält diese viel eleganter aussehen? :

reduce(lambda x,y : re.sub('\\b('+y[0]+')\\b',y[1],x) ,[("bean","robert"),("beans","cars")],"bean likes to sell his beans") 
Verwandte Themen