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.