Znalezienie ostatniego wystąpienia podciągu w ciągu znaków, zastąpienie go


Odpowiedzi:


163

To powinno wystarczyć

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
Wielkie dzięki stary. Będę musiał się temu uczyć przez minutę ... to jest użycie plasterków, prawda?
Adam Magyar

@AdamMagyar tak, kontener [a: b] wycina od a do b-1 indeksu kontenera. Jeśli pominięto „a”, przyjmuje wartość domyślną 0; jeśli pominięto „b”, domyślnie len (kontener). Operator plusa po prostu konkatenuje. Funkcja rfind, jak wskazałeś, zwraca indeks, wokół którego powinna mieć miejsce operacja zamiany.
Aditya Sihag

26

Aby wymienić od prawej:

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

W użyciu:

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

1
Zdecydowanie podoba mi się to rozwiązanie, ale posiadanie replacements=Noneparametru wydaje mi się błędem, ponieważ jeśli parametr zostanie pominięty, funkcja spowoduje błąd (próbowano w Pythonie 2.7). Sugerowałbym albo usunięcie wartości domyślnej, ustawienie jej na -1 (dla nieograniczonej liczby wymian) lub lepsze jej wykonanie replacements=1(co moim zdaniem powinno być domyślnym zachowaniem dla tej konkretnej funkcji zgodnie z tym, czego chce PO). Zgodnie z dokumentacją ten parametr jest opcjonalny, ale jeśli został podany, musi to być wartość int.
remarkov

W przypadku, gdy ktoś chce mieć jedną wkładkę na to: ". -".join("asd.asd.asd.".rsplit(".", 1)). Wszystko, co robisz, to rozdzielenie ciągu z prawej strony na jedno wystąpienie i ponowne połączenie łańcucha za pomocą zamiany.
bsplosion

14

Użyłbym wyrażenia regularnego:

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

2
To jedyna odpowiedź, która działa, jeśli w ogóle nie ma kropki. Jednak użyłbym lookahead:\.(?=[^.]*$)
georg

6

Jedna linijka to:

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


1
To jest złe . Odwracasz strunę, zastępujesz ją, a następnie cofasz z powrotem. Robisz .replacena odwróconej strunie. Oba przekazane ciągi również replacemuszą zostać odwrócone. W przeciwnym razie, gdy odwrócisz ciąg po raz drugi, wstawione litery będą odwrócone. Możesz tego użyć tylko wtedy, gdy zastępujesz jedną literę jedną literą, a nawet wtedy nie umieściłbym tego w twoim kodzie, gdyby ktoś musiał to zmienić w przyszłości i zaczął się zastanawiać, dlaczego słowo jest napisane sdrawkcab.
Boris

1

Możesz użyć poniższej funkcji, która zastępuje pierwsze wystąpienie słowa od prawej.

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

# jeśli chcesz znaleźć indeks ostatniego wystąpienia dowolnego ciągu, w naszym przypadku # znajdziemy indeks ostatniego wystąpienia z

index = a.rfind("with") 

# wynikiem będzie 44, ponieważ indeks zaczyna się od 0.


-1

Naiwne podejście:

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

Odpowiedź Adityi Sihag z jednym rfind:

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

To również odwraca ciąg zastępczy. Poza tym jest to powtórzenie odpowiedzi roota i, jak tam powiedziałem, dość nieefektywne.
Gareth Latty

@Lattyware Masz na myśli odwrócenie a?
Alex L

Mam na myśli to, że odwraca się '. -'na wyjściu.
Gareth Latty

Samo oczekiwanie, że użytkownik ręcznie odwróci literał ciągu, nie jest dobrym pomysłem - jest podatny na błędy i niejasny.
Gareth Latty

@ Lattyware Agreed. Zrobiłem to var. (Zdaję sobie sprawę, że jest to nieefektywna metoda i nie jest odpowiednia we wszystkich przypadkach - twoja replace_rightjest o wiele przyjemniejsza)
Alex L
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.