Каким образом питонический способ заменить все вхождения подстроки t в s дает список индексов, где t встречается непересекающимся образом? - PullRequest
0 голосов
/ 14 февраля 2019

В этом коде есть ошибка.Учитывая список индексов inds, где, как известно, old уже встречается (непересекающееся для двух различных индексов), и строку замены new, какова строка результата?

# Replace substring old with new in s at indices inds
def replace_substrings_at(self, inds, old, new):
    s = self._input
    inds = sorted(inds)
    res = s
    for i in inds:
        res = res[:inds[0]] + res[inds[0]:].replace(old, new, 1)
    return res    

С уважением.

Мне известно, что str.replace() имеет параметр count.Но я не хочу заменять все случаи, только определенный список, который я указываю, который может быть повсюду!


Вот лучшая версия, но есть ли более простой способ?

# Replace substring old with new in s at indices inds known to be disjoint w.r.t. old
def replace_substrings_at(self, inds, old, new):
    s = self._input
    inds = sorted(inds)
    res = s[:inds[0]]
    for k in range(len(inds)):
        i = inds[k]
        res += new
        if k + 1 < len(inds):
            res += s[i+len(old):inds[k+1]]
    return res   

Ответы [ 3 ]

0 голосов
/ 14 февраля 2019

Следующее разбивает строку в местах, где должны произойти замены, а затем соединяет детали вместе с заменой.Это использует идею заканчивать с 'other'.join(['hi ', ' is a this string of ', '']).

В этом коде предполагается, что диапазоны замены не пересекаются.Это не число в inds меньше, чем len(old) от следующего.

def replace_substrings(s, inds, old, new):
    d = len(old)
    c = 0
    l = []
    for i in sorted(inds):
        l.append(s[c:i])
        c = i+d
    l.append(s[c:])
    return new.join(l)

Используя тот же пример, что и ответ TigerhawkT3:

>>> replace_substrings('hi this is a this string of this', (3, 28), 'this', 'other')
'hi other is a this string of other'

Это стоит намного меньше дляболее длинные строки, поскольку они не используют list(s), что может привести к тому, что строка занимает от 10 до 50 байт на строковый байт.Я даже не хочу думать о квадратичном копировании, которое происходит при выполнении l[i:i+d] = new, когда len(old) != len(new).

0 голосов
/ 14 февраля 2019

Обратите внимание, что old не должен быть аргументом вашей функции, так как вам нужно только len(old) здесь.Вам нужно либо old, либо indices + len, но не оба.

Однострочник (я взял пример из ответа TigerHawkT3):

>>> s, inds, old, new = 'hi this is a this string of this', [3, 13, 28], 'this', 'other'
>>> new.join(s[slice(*ij)] for ij in zip([None]+[i+len(old) for i in inds], inds+[None]))
'hi other is a other string of other'

Пояснение. Вы хотите заменить s[inds[i]:inds[i]+len(old)] на new в s, то есть оставить все фрагменты s[inds[i-1]+len(old):inds[i]] и заполнить пробелы new.Это просто new.join.Как построить куски?[i+len(old) for i in inds] - это начальные индексы, inds - это конечные индексы:

>>> list(zip([i+len(old) for i in inds], inds))
[(7, 3), (17, 13), (32, 28)]

Вы видите, что мы должны сместить начальные индексы, чтобы получить правильные срезы.Мы хотим:

[(None, 3), (7, 13), (17, 28), (32, None)]

(None означает 0 для начального индекса и len(s) для конечного индекса).Просто вставьте None перед начальными индексами, а в конце конечных индексов:

zip([None]+[i+len(old) for i in inds], inds+[None])

Все остальное очевидно, поскольку slice(*ij) является срезом ij[0]:ij[1].

Это забавно, но (есть , но ) Я не думаю, что это питон:

>>> import this
The Zen of Python, by Tim Peters

...
Readability counts.
...
If the implementation is hard to explain, it's a bad idea.
...
0 голосов
/ 14 февраля 2019

Как я уже сказал в комментарии, превратите строку в список, замените нужные индексы заданным срезом назад, а затем снова присоединитесь к строке.

def replace_substrings(s, inds, old, new):
    l = list(s)
    d = len(old)
    new = list(new)
    for i in sorted(inds, reverse=True):
        l[i:i+d] = new
    return ''.join(l)

Результат:

>>> replace_substrings('hi this is a this string of this', (3, 28), 'this', 'other')
'hi other is a this string of other'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...