1

I'm trying to use the function str.replace(",", ";"[, count]) but when i fill in count (let's say 1) it only changes the first "," but i want to change a certain "," (working with boundries)` does anyone have a idea on how to do this?

lode
  • 13
  • 3
  • Possible duplicate of [Right-to-left string replace in Python?](http://stackoverflow.com/questions/9943504/right-to-left-string-replace-in-python) – dstudeba Oct 08 '15 at 19:18
  • It's unclear if you want to change all of them, just the last, or certain one? Maybe show a better example. – l'L'l Oct 08 '15 at 19:20
  • @I'L'I I'm sorry i was a bit unclear, i need to change a certain on (working with boundry) – lode Oct 08 '15 at 19:30

2 Answers2

3

You could rsplit and join:

s = "foo,foobar,foo"

print(";".join(s.rsplit(",",1)))

Or reverse the string, replace and reverse again:

print(s[::-1].replace(";",",",1)[::-1])

splitting actually seems a little faster:

In [7]: timeit s[::-1].replace(";",",",1)[::-1]
1000000 loops, best of 3: 521 ns per loop

In [8]: timeit ";".join(s.rsplit(",",1))
1000000 loops, best of 3: 416 ns per loop

If you want to change the ith occurrence:

def change_ith(st, ith, sep, rep):
    return "".join([s + rep if i == ith else s + sep
                    for i, s in enumerate(st.split(sep, ith), 1)]).rstrip(sep)

Output:

In [15]: s = "foo,foo,bar,foo,foo"

In [16]: change_ith(s, 1, ",",";")
Out[16]: 'foo;foo,bar,foo,foo'

In [17]: change_ith(s, 2, ",",";")
Out[17]: 'foo,foo;bar,foo,foo'

In [18]: change_ith(s, 3, ",",";")
Out[18]: 'foo,foo,bar;foo,foo'

In [19]: change_ith(s, 4, ",",";")
Out[19]: 'foo,foo,bar,foo;foo'

There are cases where join will could give incorrect output if you had a string ending in the sep and a few other edge cases, to get a more robust function we would need to use a regex passing a lambda as the repl arg and using itertools.count to count how many matches we got:

import re
from itertools import count
def change_ith(st, ith, sep, rep):
    return re.sub(sep, lambda m, c=count(1): rep if next(c) == ith else m.group(0), st)

Or applying the same logic to join:

from itertools import count
def change_ith(st, ith, sep, rep):
    cn = count(1)
    return  "".join([rep if ch == sep and next(cn) == ith else ch 
                   for ch in st])
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0

You should reverse, replace, and reverse again. I use reverse indexing for that in the example below:

s = "one, two, three, four, five"

print str.replace(s[::-1], ',', ';', 1)[::-1]
heltonbiker
  • 26,657
  • 28
  • 137
  • 252