Encontrar la última aparición de subcadena en cadena, reemplazando eso

Respuestas:

163

Esto debería hacerlo

old_string = "this is going to have a full stop. some written sstuff!"
k = old_string.rfind(".")
new_string = old_string[:k] + ". - " + old_string[k+1:]
Aditya Sihag
fuente
1
Muchas gracias tio. Tendré que estudiar eso por un minuto ... esto es utilizar rodajas, ¿verdad?
Adam Magyar
@AdamMagyar sí, el contenedor [a: b] corta desde un índice hasta b-1 del contenedor. Si se omite 'a', el valor predeterminado es 0; si se omite 'b', el valor predeterminado es len (contenedor). El operador más simplemente concatena. La función rfind, como señaló, devuelve el índice alrededor del cual debe realizarse la operación de reemplazo.
Aditya Sihag
26

Para reemplazar desde la derecha:

def replace_right(source, target, replacement, replacements=None):
    return replacement.join(source.rsplit(target, replacements))

En uso:

>>> replace_right("asd.asd.asd.", ".", ". -", 1)
'asd.asd.asd. -'
Varinder Singh
fuente
1
Definitivamente me gusta esta solución, pero tener un replacements=Noneparámetro me parece un error porque si se omite el parámetro, la función dará un error (probado en Python 2.7). Sugeriría eliminar el valor predeterminado, establecerlo en -1 (para reemplazos ilimitados) o mejor hacerlo replacements=1(que creo que debería ser el comportamiento predeterminado para esta función en particular de acuerdo con lo que quiere el OP). De acuerdo con la documentación, este parámetro es opcional, pero debe ser un int si se proporciona.
remarkov
En caso de que alguien quiere una sola línea para esto: ". -".join("asd.asd.asd.".rsplit(".", 1)). Todo lo que está haciendo es realizar una división de cadena desde el lado derecho para una aparición y volver a unir la cadena utilizando el reemplazo.
bsplosion
14

Usaría una expresión regular:

import re
new_list = [re.sub(r"\.(?=[^.]*$)", r". - ", s) for s in old_list]
Tim Pietzcker
fuente
2
Esta es la única respuesta que funciona si no hay ningún punto. Que haría uso de una búsqueda hacia delante sin embargo:\.(?=[^.]*$)
Georg
6

Un trazador de líneas sería:

str=str[::-1].replace(".",".-",1)[::-1]

mazs
fuente
1
Esto está mal . Estás invirtiendo la cuerda, reemplazándola y luego invirtiéndola. Lo estás haciendo .replacecon una cuerda invertida. Ambas cuerdas pasaron para replacetener que invertirse también. De lo contrario, cuando invierta la cadena por segunda vez, las letras que acaba de insertar estarán al revés. Solo puede usar esto si está reemplazando una letra con una letra, e incluso entonces no pondría esto en su código en caso de que alguien tenga que cambiarlo en el futuro y comience a preguntarse por qué se escribe una palabra sdrawkcab.
Boris
1

Puede usar la función a continuación que reemplaza la primera aparición de la palabra de la derecha.

def replace_from_right(text: str, original_text: str, new_text: str) -> str:
    """ Replace first occurrence of original_text by new_text. """
    return text[::-1].replace(original_text[::-1], new_text[::-1], 1)[::-1]
bambuste
fuente
0
a = "A long string with a . in the middle ending with ."

# si desea encontrar el índice de la última aparición de cualquier cadena, en nuestro caso # encontraremos el índice de la última aparición de con

index = a.rfind("with") 

# el resultado será 44, ya que el índice comienza desde 0.

Arpan Saini
fuente
-1

Enfoque ingenuo:

a = "A long string with a . in the middle ending with ."
fchar = '.'
rchar = '. -'
a[::-1].replace(fchar, rchar[::-1], 1)[::-1]

Out[2]: 'A long string with a . in the middle ending with . -'

La respuesta de Aditya Sihag con un solo rfind:

pos = a.rfind('.')
a[:pos] + '. -' + a[pos+1:]
Alex L
fuente
Esto también invierte la cuerda de reemplazo. Aparte de eso, es una repetición de la respuesta de root y, como digo allí, bastante ineficiente.
Gareth Latty
@Lattyware ¿Quieres decir que se invierte a?
Alex L
Quiero decir que se invierte '. -'en la salida.
Gareth Latty
Esperar que el usuario invierta el literal de cadena a mano no es una gran idea; es propenso a errores y poco claro.
Gareth Latty
@Lattyware de acuerdo. Lo hice var. (Me doy cuenta de que es un método ineficaz y no es adecuado en todos los casos; el suyo replace_rightes mucho mejor)
Alex L