Recherche de la dernière occurrence de sous-chaîne dans la chaîne, remplacement de cette

104

J'ai donc une longue liste de chaînes dans le même format, et je veux trouver le dernier "." caractère dans chacun d'eux, et remplacez-le par ". -". J'ai essayé d'utiliser rfind, mais je n'arrive pas à l'utiliser correctement pour ce faire.

Adam Magyar
la source
Double
Graham

Réponses:

163

Cela devrait le faire

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
la source
1
Merci beaucoup mec. Je vais devoir étudier cela pendant une minute ... c'est en utilisant des tranches, non?
Adam Magyar
@AdamMagyar oui, le conteneur [a: b] tranche d'un index jusqu'à b-1 du conteneur. Si «a» est omis, la valeur par défaut est 0; si 'b' est omis, la valeur par défaut est len ​​(container). L'opérateur plus concatène simplement. La fonction rfind comme vous l'avez indiqué renvoie l'index autour duquel l'opération de remplacement doit avoir lieu.
Aditya Sihag
26

Pour remplacer par la droite:

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

Utilisé:

>>> replace_right("asd.asd.asd.", ".", ". -", 1)
'asd.asd.asd. -'
Varinder Singh
la source
1
J'aime vraiment cette solution mais avoir un replacements=Noneparamètre me semble être une erreur car si le paramètre est omis, la fonction donnera une erreur (essayé en Python 2.7). Je suggérerais de supprimer la valeur par défaut, de la définir sur -1 (pour des remplacements illimités) ou de mieux la faire replacements=1(ce qui, à mon avis, devrait être le comportement par défaut pour cette fonction particulière en fonction de ce que veut l'OP). Selon la documentation, ce paramètre est facultatif, mais il doit être un int s'il est donné.
remarque
Dans le cas où quelqu'un veut un one-liner pour cela: ". -".join("asd.asd.asd.".rsplit(".", 1)). Tout ce que vous faites est d'effectuer une séparation de chaîne du côté droit pour 1 occurrence et de joindre à nouveau la chaîne en utilisant le remplacement.
bsplosion le
14

J'utiliserais un regex:

import re
new_list = [re.sub(r"\.(?=[^.]*$)", r". - ", s) for s in old_list]
Tim Pietzcker
la source
2
C'est la seule réponse qui fonctionne s'il n'y a pas de point du tout. J'utiliserais un lookahead cependant:\.(?=[^.]*$)
georg
6

Une seule ligne serait:

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

labyrinthes
la source
1
C'est faux . Vous inversez la chaîne, vous la remplacez, puis vous l'inversez. Vous faites .replacesur une chaîne inversée. Les deux chaînes passées doivent replaceégalement être inversées. Sinon, lorsque vous inversez la chaîne une deuxième fois, les lettres que vous venez d'insérer seront à l'envers. Vous ne pouvez l'utiliser que si vous remplacez une lettre par une lettre, et même dans ce cas, je ne mettrais pas cela dans votre code au cas où quelqu'un devrait le changer à l'avenir et commencer à se demander pourquoi un mot est écrit sdrawkcab.
Boris
1

Vous pouvez utiliser la fonction ci-dessous qui remplace la première occurrence du mot de droite.

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
la source
0
a = "A long string with a . in the middle ending with ."

# si vous voulez trouver l'index de la dernière occurrence de n'importe quelle chaîne, dans notre cas, nous trouverons # l'index de la dernière occurrence de avec

index = a.rfind("with") 

# le résultat sera 44, car l'index commence à 0.

Arpan Saini
la source
-1

Approche naïve:

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 réponse d'Aditya Sihag avec un seul rfind:

pos = a.rfind('.')
a[:pos] + '. -' + a[pos+1:]
Alex L
la source
Cela inverse également la chaîne de remplacement. En dehors de cela, c'est une répétition de la réponse de root et, comme je le dis ici, assez inefficace.
Gareth Latty
@Lattyware Vous voulez dire qu'il s'inverse a?
Alex L
Je veux dire qu'il s'inverse '. -'dans la sortie.
Gareth Latty
S'attendre à ce que l'utilisateur inverse la chaîne littérale à la main n'est pas une bonne idée - il est sujet aux erreurs et n'est pas clair.
Gareth Latty
@Lattyware accepté. J'en ai fait un var. (Je me rends compte que c'est une méthode inefficace, et ne convient pas dans tous les cas - vous replace_rightêtes beaucoup plus gentil)
Alex L