Search code examples
pythonregexpython-re

Replacing sub-string occurrences with elements of a given list


Suppose I have a string that has the same sub-string repeated multiple times and I want to replace each occurrence with a different element from a list.

For example, consider this scenario:

pattern = "_____" # repeated pattern
s = "a(_____), b(_____), c(_____)"
r = [0,1,2] # elements to insert

The goal is to obtain a string of the form:

s = "a(_001_), b(_002_), c(_003_)"

The number of occurrences is known, and the list r has the same length as the number of occurrences (3 in the previous example) and contains increasing integers starting from 0.

I've came up with this solution:

import re

pattern = "_____"
s = "a(_____), b(_____), c(_____)"

l = [m.start() for m in re.finditer(pattern, s)]
i = 0
for el in l:
    s = s[:el] + f"_{str(i).zfill(5 - 2)}_" + s[el + 5:]
    i += 1

print(s)

Output: a(_000_), b(_001_), c(_002_)

This solves my problem, but it seems to me a bit cumbersome, especially the for-loop. Is there a better way, maybe more "pythonic" (intended as concise, possibly elegant, whatever it means) to solve the task?


Solution

  • You can simply use re.sub() method to replace each occurrence of the pattern with a different element from the list.

    import re
    
    pattern = re.compile("_____")
    s = "a(_____), b(_____), c(_____)"
    r = [0,1,2]
    
    for val in r:
        s = re.sub(pattern, f"_{val:03d}_", s, count=1)
    print(s)
    

    You can also choose to go with this approach without re using the values in the r list with their indexes respectively:

    r = [0,1,2]
    
    s = ", ".join(f"{'abc'[i]}(_{val:03d}_)" for i, val in enumerate(r))
    print(s)
    

    a(_000_), b(_001_), c(_002_)