简体   繁体   中英

Python 3: Formatting a string with multiple same keywords but unique strings to replace them

I'm wondering how to use a list to format multiple of the same keyword in Python 3.4. The way I have it set up is a user can pass in a string that has multiple keywords for names that the program will generate in their place, and the result should be a sentence with the keywords replaced with names.

I have already created a method to generate the names based on how many the program sees in the strings the user passes in, but cannot replace them at once because of the nature of the string. Since the string has multiple of the same keyword (for example {name}), I need to be able to replace each one of them with a unique string. Is that possible in Python 3.4?

The string the user passes in could be

"{name} had a wonderful day at the park, but then {name} came and ruined it"

and after the program has generated the names it should be

"John had a wonderful day at the park, but then Bob came and ruined it"

Cheers.

EDIT: To add, I didn't find anything about using lists or having multiple keywords but unique replacements, so if I have to do it another way than replace it's OK too.

You can use string.replace with the optional count parameter and limit it to only replace one name each time:

>>> names = ['John', 'Bob']
>>> message = "{name} had a wonderful day at the park, but then {name} came and ruined it"
>>> i = 0;
>>> while '{name}' in message:
...     message = message.replace('{name}', names[i], 1)
...     i += 1
... 
>>> message
'John had a wonderful day at the park, but then Bob came and ruined it'

You can use the count parameter:

>>> s = "{name} had a wonderful day at the park, but then {name} came and ruined it"
>>> s = s.replace('{name}', 'John', count=1)
>>> s
'John had a wonderful day at the park, but then {name} came and ruined it'

>>> s = s.replace('{name}', 'Bob', count=1)
>>> s
'John had a wonderful day at the park, but then Bob came and ruined it'

If you have pre-generated a list of items for each replacement based on how many times they occur, you can use re.sub to programmatically pick the next item from the list. This will have much better performance than str.replace , esp. if you have a large dictionary of keywords and and a large text.

For example:

import re

# Function to look up an item and return the next thing in its list.
def replace(m):
    return D[m.group(1)].pop(0)

D = {'name' : ['John','Bob'], 'place' : ['park']}

text = "{name} had a wonderful day at the {place}, but then {name} came and ruined it"
new_text = re.sub('{(.*?)}',replace,text)
print(new_text)

Output:

John had a wonderful day at the park, but then Bob came and ruined it

It seems like you'd want a different variable for different names, however. Then you can just use format with a dictionary:

import re

D = {'name1':'John', 'name2':'Bob', 'place':'park'}
text = "{name1} had a wonderful day at the {place}, but then {name2} came and ruined it. {name2} is a jerk!"
print(text.format(**D))

Output:

John had a wonderful day at the park, but then Bob came and ruined it. Bob is a jerk!

If I understand you right, this should work:
first_name = Bob
second_name = Sam
"%s had a wonderful day at the park, but then %s came and ruined it" % (first_name, second_name)

Probably the cleanest way to do it

In case the phrase is always well spaced as in the example, you can do

s = "{name} had a wonderful day at the park, but then {name} came and ruined it"
names = ['John', 'Bob']
ni = iter(names)
outs = ' '.join(next(ni) if el=='{name}' else el for el in s.split())
print(outs)

which produces

'John had a wonderful day at the park, but then Bob came and ruined it'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM