Encontrar a última ocorrência de substring em string, substituindo


Respostas:


163

Isso deve servir

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

1
Muito obrigado cara. Vou ter que estudar isso por um minuto ... isso é utilizar fatias, certo?
Adam Magyar

@AdamMagyar sim, fatias do recipiente [a: b] de um índice até b-1 do recipiente. Se 'a' for omitido, o padrão é 0; se 'b' for omitido, o padrão é len (container). O operador mais apenas concatena. A função rfind como você apontou retorna o índice em torno do qual a operação de substituição deve ocorrer.
Aditya Sihag

26

Para substituir da direita:

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

Em uso:

>>> replace_right("asd.asd.asd.", ".", ". -", 1)
'asd.asd.asd. -'

1
Eu definitivamente gosto dessa solução, mas ter replacements=Noneparâmetro parece um erro para mim, porque se o parâmetro for omitido, a função dará um erro (tentado em Python 2.7). Eu sugeriria remover o valor padrão, configurá-lo como -1 (para substituições ilimitadas) ou melhor torná-lo replacements=1(que eu acho que deve ser o comportamento padrão para esta função específica de acordo com o que o OP deseja). De acordo com a documentação, este parâmetro é opcional, mas deve ser um int, se fornecido.
notov

Caso alguém queira uma frase para isso: ". -".join("asd.asd.asd.".rsplit(".", 1)). Tudo o que você está fazendo é realizar uma divisão da corda do lado direito para 1 ocorrência e unir a corda novamente usando a substituição.
bsplosion

14

Eu usaria um regex:

import re
new_list = [re.sub(r"\.(?=[^.]*$)", r". - ", s) for s in old_list]

2
Esta é a única resposta que funciona se não houver nenhum ponto. Eu usaria um lookahead:\.(?=[^.]*$)
georg

6

Um forro seria:

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


1
Isso está errado . Você está invertendo a corda, recolocando-a e depois revertendo-a de volta. Você está fazendo .replaceuma corda invertida. Ambas as cordas passaram a replaceter que ser invertidas também. Caso contrário, quando você inverter a string uma segunda vez, as letras que você acabou de inserir estarão invertidas. Você só pode usar isso se estiver substituindo uma letra por uma letra, e mesmo assim eu não colocaria isso no seu código caso alguém tenha que alterá-lo no futuro e comece a se perguntar por que uma palavra foi escrita sdrawkcab.
Boris

1

Você pode usar a função abaixo que substitui a primeira ocorrência da palavra da direita.

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]

0
a = "A long string with a . in the middle ending with ."

# se você quiser encontrar o índice da última ocorrência de qualquer string, no nosso caso, # encontraremos o índice da última ocorrência de com

index = a.rfind("with") 

# o resultado será 44, pois o índice começa em 0.


-1

Abordagem ingênua:

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

A resposta de Aditya Sihag com um único rfind:

pos = a.rfind('.')
a[:pos] + '. -' + a[pos+1:]

Isso também inverte a string de substituição. Fora isso, é uma repetição da resposta do root e, como eu disse lá, bastante ineficiente.
Gareth Latty

@Lattyware Você quer dizer que inverte a?
Alex L

Quero dizer, ele reverte '. -'na saída.
Gareth Latty

Esperar que o usuário inverta o literal da string manualmente não é uma boa ideia - é propenso a erros e confuso.
Gareth Latty

@Lattyware aprovado. Eu fiz um var. (Eu percebo que é um método ineficiente e não é adequado em todos os casos - o seu replace_righté muito melhor)
Alex L
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.