Supongamos que tengo la siguiente oración:

bean likes to sell his beans

Y quiero reemplazar todas las ocurrencias de palabras específicas con otras palabras. Por ejemplo, bean a robert y beans a cars.

No puedo usar str.replace simplemente porque en este caso cambiará beans a roberts.

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

Solo necesito cambiar las palabras completas, no las ocurrencias de la palabra en la otra palabra. Creo que puedo lograr esto usando expresiones regulares pero no sé cómo hacerlo bien.

13
FrozenHeart 3 sep. 2014 a las 00:19

4 respuestas

La mejor respuesta

Si usa expresiones regulares, puede especificar límites de palabras con \b:

import re

sentence = 'bean likes to sell his beans'

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

Aquí 'beans' no se cambia (a 'roberts') porque la 's' al final no es un límite entre las palabras: \b coincide con la cadena vacía, pero solo al principio o fin de una palabra.

El segundo reemplazo para completar:

sentence = re.sub(r'\bbeans\b', 'cars', sentence)
# 'robert likes to sell his cars'
17
Alex Riley 22 dic. 2015 a las 12:26
"bean likes to sell his beans".replace("beans", "cars").replace("bean", "robert")

Reemplazará todas las instancias de "beans" con "cars" y "bean" con "robert". Esto funciona porque .replace() devuelve una instancia modificada de la cadena original. Como tal, puedes pensar en etapas. Básicamente funciona de esta manera:

 >>> 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')
-1
Kevin London 2 sep. 2014 a las 20:22

Si reemplaza cada palabra de una en una, puede reemplazar las palabras varias veces (y no obtener lo que desea). Para evitar esto, puede usar una función o 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)

De esa manera, una vez que bean sea reemplazado por robert, no se modificará nuevamente (incluso si robert también está en su lista de palabras de entrada).

Según lo sugerido por georg , edité esta respuesta con dict.get(key, default_value). Solución alternativa (también sugerida por georg ):

str_out = re.sub(r'\b(%s)\b' % '|'.join(d.keys()), lambda m:d.get(m.group(1), m.group(1)), str_in)
4
nicolas 2 sep. 2014 a las 22:58

Sé que ha pasado mucho tiempo, pero ¿esto se ve mucho más elegante? :

reduce(lambda x,y : re.sub('\\b('+y[0]+')\\b',y[1],x) ,[("bean","robert"),("beans","cars")],"bean likes to sell his beans")
-1
Akshay Hazari 3 nov. 2015 a las 04:08