Нахождение последнего вхождения подстроки в строку, замена этого


104

Итак, у меня есть длинный список строк в том же формате, и я хочу найти последнюю "." в каждом из них и замените его на ". -". Я пробовал использовать rfind, но, похоже, не могу правильно использовать его для этого.


Ответы:


163

Это должно сделать это

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
Большое спасибо, чувак. Придется изучить это в течение минуты ... это использование срезов, верно?
Adam Magyar

@AdamMagyar да, контейнер [a: b] разрезает от a до индекса b-1 контейнера. Если «а» опущено, то по умолчанию используется значение 0; если 'b' опущено, по умолчанию используется len (контейнер). Оператор «плюс» просто объединяется. Функция rfind, как вы указали, возвращает индекс, вокруг которого должна выполняться операция замены.
Адитья Сихаг

26

Для замены справа:

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

В использовании:

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

1
Мне определенно нравится это решение, но наличие replacements=Noneпараметра кажется мне ошибкой, потому что, если параметр не указан, функция выдаст ошибку (пробовал в Python 2.7). Я бы предложил либо удалить значение по умолчанию, либо установить его на -1 (для неограниченного количества замен), либо лучше сделать его replacements=1(что, я думаю, должно быть поведением по умолчанию для этой конкретной функции в соответствии с тем, что хочет OP). Согласно документации, этот параметр не является обязательным, но должен быть целым числом, если задан.
Репликов

В случае , если кто -то хочет Однострочник для этого: ". -".join("asd.asd.asd.".rsplit(".", 1)). Все, что вы делаете, это выполняете разделение строки с правой стороны на 1 вхождение и снова присоединяете строку с помощью замены.
bsplosion

14

Я бы использовал регулярное выражение:

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

2
Это единственный ответ, который работает, если точки вообще нет. Хотя я бы использовал опережающий \.(?=[^.]*$)
взгляд

6

Один лайнер будет:

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


1
Это неправильно . Вы переворачиваете струну, заменяете ее, а затем переворачиваете обратно. Вы делаете .replaceна перевернутой струне. Обе строки replaceтоже должны быть перевернуты. В противном случае, когда вы перевернете строку во второй раз, только что вставленные буквы будут перевернуты. Вы можете использовать это только в том случае, если вы заменяете одну букву одной буквой, и даже тогда я бы не стал вставлять это в ваш код, если кто-то должен будет изменить его в будущем и начнет задаваться вопросом, почему слово написано sdrawkcab.
Борис

1

Вы можете использовать функцию ниже, которая заменяет первое вхождение слова справа.

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

# если вы хотите найти индекс последнего вхождения любой строки, в нашем случае мы # найдем индекс последнего вхождения с

index = a.rfind("with") 

# результат будет 44, так как индекс начинается с 0.


-1

Наивный подход:

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

Ответ Адитьи Сихага одним rfind:

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

Это также меняет местами строку замены. В остальном это повторение ответа root, и, как я там сказал, довольно неэффективно.
Гарет Латти,

@Lattyware Вы имеете в виду, что это наоборот a?
Alex L

Я имею в виду, что все наоборот '. -' на выходе на .
Гарет Латти,

Ожидать, что пользователь перевернет строковый литерал вручную, - не лучшая идея - это чревато ошибками и непонятно.
Гарет Латти,

@Lattyware Согласен. Я сделал это вар. (Я понимаю, что это неэффективный метод и он подходит не во всех случаях - ваш replace_rightнамного лучше)
Alex L
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.