Zed
Zed

Reputation: 5931

Easy way to replace placeholders in string with the list of values?

I have a long string that contains placeholders, that should be replaced with some data.

strOut = "text text {{ }} text text {{ }}"

with this pattern

pattern = r'\{{(.+?)\}}'

It's easy for me to do something like this

pattern.sub(self.mymethod, strOut)

where mymethod will be called for substitution. It actually works great. However, this is the problem now. I need to replace all placeholders in string with the values from a list. For example, this is the string again:

strOut = "text text {{ }} text {{ }} text"

It will always have undetermined number of placeholders. If I also have a list of let's say 2 values

myList = [2, 3]

I need a way to inject these values into placeholders, and end up with this

"text text 2 text 3 text"

Number of values in a list and number of placeholder will always be the same, I just don't know in advance how many there will be.

Upvotes: 2

Views: 9631

Answers (5)

Vlad Bezden
Vlad Bezden

Reputation: 89577

You can use format function and pass list with argument unpacking (*)

>>> myList = [2, 3]
>>> strOut = 'text text {} text {} text'
>>> print(strOut.format(*myList))
text text 2 text 3 text

Upvotes: 1

Kalyanaraman Santhanam
Kalyanaraman Santhanam

Reputation: 1389

my_csv = '%(first)s,%(last)s'
print my_csv % dict(last='Doe', first='John')  # John,Doe

I like this for the following reasons :

  • the ordering of values is no longer needed
  • multiple placeholders can be replaced in one shot.

inspired from https://stackoverflow.com/a/11023271/2147228

Upvotes: 7

Jon Clements
Jon Clements

Reputation: 142156

Sample code:

>>> strOut = "text text {{ }} text text {{ }}"
>>> pattern = r'\{{(.+?)\}}'
>>> import re
>>> re.findall(pattern, strOut)
[' ', ' ']
>>> items = iter(str(el) for el in [1, 2])
# as pointed out by @eyquem, this can also be written as:
# items = imap(str, [1, 2])

>>> re.sub(pattern, lambda L: next(items), strOut)
'text text 1 text text 2'

This will break if there's not enough parameters to meet the placeholders, but just ignore the remainder otherwise.

And if you're using 2.7+, you're laughing if you can get away with {} as a place holder, as you can then just use 'text text {} text text {}'.format(*[1,2]) for instance

And for "fun"

(ab)using the lambda, you can do:

re.sub(pattern, lambda i, j=(str(el) for el in [1, 2]): next(j), strOut)

Upvotes: 3

James Waldby - jwpat7
James Waldby - jwpat7

Reputation: 8711

If there are no appearances of '{}' (as opposed to '{{ }}') in your strOut text, the following approach works. For strOut and myList as shown, the string it produces is 'text text 2 text 3 text'.

strOut = "text text {{ }} text {{ }} text"
myList = [2, 3]
strOut.replace('{{ }}','{}').format(*myList)

Upvotes: 1

RocketDonkey
RocketDonkey

Reputation: 37259

You could try something like this (it uses the count parameter of re.sub):

In [1]: import re

In [2]: strOut = "text text {{ }} text text {{ }}"

In [3]: pattern = r'\{{(.+?)\}}'

In [4]: reduce(lambda x, y: re.sub(pattern, str(y), x, 1), [2, 3], strOut)
Out[4]: 'text text 2 text text 3'

Upvotes: 0

Related Questions