1

I have a string, for example:

s = "I ? am ? a ? string"

And I have a list equal in length to the number of ? in the string:

l = ['1', '2', '3']

What is a pythonic way to return s with each consecutive ? replaced with the values in l?, e.g.:

s_new = 'I 1 am 2 a 3 string'
njminchin
  • 408
  • 3
  • 13

2 Answers2

3

2 Methods:

# Method 1
s = "I ? am ? a ? string"
l = ['1', '2', '3']

for i in l:
    s = s.replace('?', i, 1) 

print(s)
# Output: I 1 am 2 a 3 string

# Method 2
from functools import reduce
s = "I ? am ? a ? string"
l = ['1', '2', '3']

s_new = reduce(lambda x, y: x.replace('?', y, 1), l, s)

print(s_new) 
# Output: I 1 am 2 a 3 string
Jiya
  • 745
  • 8
  • 19
  • 2
    I'd love to spend time to actually understand reduce and lambda expressions! Thanks for the 2 methods. I didn't realise replace allowed replacing a limited number of occurrences :) – njminchin Nov 30 '22 at 06:10
3

If the placeholders (not "delimiters") were {} rather than ?, this would be exactly how the built-in .format method handles empty {} (along with a lot more power). So, we can simply replace the placeholders first, and then use that functionality:

>>> s = "I ? am ? a ? string"
>>> l = ['1', '2', '3']
>>> s.replace('?', '{}').format(*l)
'I 1 am 2 a 3 string'

Notice that .format expects each value as a separate argument, so we use * to unpack the list.

If the original string contains { or } which must be preserved, we can first escape them by doubling them up:

>>> s = "I ? {am} ? a ? string"
>>> l = ['1', '2', '3']
>>> s.replace('?', '{}').format(*l)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'am'
>>> s.replace('{', '{{').replace('}', '}}').replace('?', '{}').format(*l)
'I 1 {am} 2 a 3 string'
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153