2014-09-02 16 views
7

Załóżmy, że mam następujące zdanie:Wymień wszystkie wystąpienia określonych słów

bean likes to sell his beans 

i chcę zastąpić wszystkie wystąpienia określonych słów z innymi słowami. Na przykład bean do robert i beans do cars.

Nie mogę po prostu użyć str.replace, ponieważ w takim przypadku zmieni on beans na roberts.

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

Muszę zmienić tylko całe słowa, a nie wystąpienia słowa w innym słowie. Myślę, że mogę to osiągnąć za pomocą wyrażeń regularnych, ale nie wiem, jak to zrobić dobrze.

+0

mogłeś 'split()' The tekst słowami pierwszy – cmd

Odpowiedz

14

Jeśli używasz regex, można określić granice słowo z \b:

import re 

sentence = 'bean likes to sell his beans' 

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

Oto fasoli "nie ulega zmianie (na 'Roberts'), ponieważ„s "na końcu nie jest granica między słowami: \b dopasowuje pusty ciąg, ale tylko na początku lub na końcu słowa.

Drugi zamiennikiem dla kompletności:

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

dlaczego nawiasy? – Jerry

+1

Przypuszczam, że nawiasy nie są konieczne, po prostu sprawiły, że wyrażenie regularne jest bardziej czytelne (przynajmniej dla mnie). –

+0

Z jakiegoś powodu nie wydaje się, aby wystąpiło w całości w USA – Kahless

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

Zamieni wszystkie wystąpienia "fasoli" na "samochody" i "fasola" na "robert". Działa to, ponieważ .replace() zwraca zmodyfikowaną instancję oryginalnego łańcucha. Jako taki, możesz myśleć o tym etapami. To zasadniczo działa w ten sposób:

>>> 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

nie mogę zrobić to w ten sposób w prawdziwym zadaniem, ponieważ postanowienie to zastępstwo jest niezdefiniowany – FrozenHeart

3

Jeśli zastąpi każde słowo po jednym na raz, można zastąpić słowa kilka razy (a nie to, co chcesz). Aby tego uniknąć, można użyć funkcji lub lambda:

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) 

ten sposób, po raz bean zastępuje robert, nie zostanie ponownie zmodyfikowany (nawet jeśli robert jest również na liście wejściowej słów).

Jak sugeruje Georg, ja edytowany tę odpowiedź z dict.get(key, default_value). rozwiązanie alternatywna (również sugerowane przez Georg):

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

Powinieneś być w stanie uczynić to prostszym (i szybszym) i usunąć 'if', aby bezpośrednio przejrzeć dyktaturę, jeśli używasz' \ bbeans? \ B' dla wyrażeń regularnych i użyj 'm.group (0)' (dla całego dopasowania) w lambda. – Jerry

+0

Chciałbym, żeby to było wystarczająco ogólne, więc 1 wyrażenie może poradzić sobie z dowolnym tekstem wejściowym + dowolną listą słów do zastąpienia. Więc nie chcę "fasoli" w moim regex. – seb

+0

Rozumiem. Po prostu sprawdzi każde słowo i uważam, że to główne wąskie gardło. – Jerry

-1

znam jego dawna Ale czy to wygląda o wiele bardziej elegancki? :

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