Can we not make double use of the string.replace
method?
For example:
a = "foobarfoofoobarbar"
print(a)
>> foobarfoofoobarbar
n_instance_to_replace = 2
a = a.replace("foo", "FOO", n_instance_to_replace).replace("FOO","foo", n_instance_to_replace - 1)
print(a)
>> foobarFOOfoobarbar
Basically the first .replace("foo", "FOO", n_instance_to_replace)
turns all substrings of "foo"
up to the second occurrence into "FOO"
, and then the second .replace("FOO", "foo", n_instance_to_replace)
turns all the "FOO"
s preceding the one we wanted to change back to "foo"
.
This can be expanded to change each nth repeat substring like so:
a = "foobarfoofoobarbar"*3 # create string with repeat "foo"s
n_instance = 2 # set nth substrings of "foo" to be replaced
# Replace nth subs in supstring
for n in range(n_instance, a.count("foo")+n_instance, n_instance)[::-1]:
a = a.replace("foo","FOO", n).replace("FOO","foo", n-1)
print(n, n-1, a)
>> 10 9 foobarfoofoobarbarfoobarfoofoobarbarfoobarfoofoobarbar
>> 8 7 foobarfoofoobarbarfoobarfoofoobarbarfoobarFOOfoobarbar
>> 6 5 foobarfoofoobarbarfoobarfooFOObarbarfoobarFOOfoobarbar
...
>> 2 1 foobarFOOfoobarbarFOObarfooFOObarbarfoobarFOOfoobarbar
The range()
is basically set to find the index of each "foo"
starting from the end of the a
string. As a function this could simply be:
def repl_subst(sup="foobarfoofoobarbar"*5, sub="foo", sub_repl="FOO", n_instance=2):
for n in range(n_instance, sup.count(sub)+n_instance, n_instance)[::-1]:
sup = sup.replace(sub, sub_repl, n).replace(sub_repl, sub, n-1)
return sup
a = repl_substr()
Great thing is, no external packages required.
EDIT: I think I misinterpreted your question and now see that actually want to keep replacing every nth instances of "foo"
rather than a single instance. I'll have a think to see if .replace()
can still be used. But, I don't think it will be possible. The other answer suggesting using regular expressions is always a good call.