Home > front end >  python how can string .replace() only calc the new value if the old value is found in the string
python how can string .replace() only calc the new value if the old value is found in the string

Time:06-17

I have a code similar to this:

s = some_template
s = s.replace('<HOLDER1>',data1)
s = s.replace('<HOLDER2>',data2)
s = s.replace('<HOLDER4>',data3)
... #(about 30 similar lines)

where data1/data2/etc is often a call to a function which might take a while to calculate. for example:

s = s.replace('<HOLDER5>',calc_factorial(1000))

in order to save on runtime, i want the string.replace() method to calculate the new value only if the old value is found in str. this can be achieved by:

if '<HOLDER1>' in str:
    s = s.replace('<HOLDER1>',data1)
if '<HOLDER2>' in str:
    s = s.replace('<HOLDER2>',data2)
if '<HOLDER3>' in str:
    s = s.replace('<HOLDER3>',data3)
...

but i don't like this solutions because it takes double the number of lines of code which will be really messy and also finds the old value in s twice for each holder..

any ideas?

Thanks!

CodePudding user response:

str is immutable. You can't change it, only creating a new instance is allowed.

You could do something like:

def replace_many(replacements, s):
    for pattern, replacement in replacements:
        s = s.replace(pattern, replacement)
    return s

without_replacements = 'this_will_be_replaced, will it?'
replacements = [('this_will_be_replaced', 'by_this')]

with_replacements = replace_many(replacements, without_replacements)

You can easily make it lazy:

def replace_many_lazy(replacements, s):
    for pattern, replacement_func in replacements:
        if pattern in s:
            s = s.replace(pattern, replacement_func())
    return s

without_replacements = 'this_will_be_replaced, will it?'
replacements = [('this_will_be_replaced', lambda: 'by_this')]

with_replacements = replace_many_lazy(replacements, without_replacements)

...now you don't do the expensive computation unless necessary.

CodePudding user response:

a couple of suggestions. First, please do not shadow the builtin str name.

Next, the index of function might be useful, however, you will need a try-catch block if the Holder doesn't exist in the string.

s = "my name is <HOLDER1>. What's yours? <HOLDER2>"
s.index("<HOLDER1>")
11
s.index("<HOLDER3>")
Traceback (most recent call last):
  File "C:\Users\klavl\AppData\Local\Programs\Python\Python310\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
ValueError: substring not found

This would be the structure.

s = "my name is <HOLDER1>. What's yours? <HOLDER2>"
if (index := s.index("<HOLDER1>")) >= 0:
    s = s[:index]   "MYNAME"   s[index   len("<HOLDER1>"):]
    
s
"my name is MYNAME. What's yours? <HOLDER2>"
  • Related