1

I'd like to replace occurrences of string with different values (from dictionary).

string = 'asfd @@@ fdsfd @@@ ffds @@@ asdf'
kv = {1: 'hi', 2: 'there', 3: 'bla'}

Expected:

string = 'asfd hi fdsfd there ffds bla asdf'

I've tried several solutions particularly with .replace or re.sub but still didn't find a good one.

1
  • 5
    what you have tried? Commented Feb 7, 2019 at 11:27

5 Answers 5

8

A one-line solution:

string.replace('@@@', '{}', len(kv)).format(*kv.values())

Short explanation:

  • Replace all '@@@' strings with the python string formatting identifier '{}'. len(kv) reduces the number of replaces to the length of the dict, avoiding IndexError when the dict has less elements than the number of '@@@' in the string
  • extract dictionary values with kv.values()
  • unpack dictionary values with *kv.values() and pass this as argument to the string format method.

Sample code execution:
Input

string = 'asfd @@@ fdsfd @@@ ffds @@@ asdf'
kv = {'1': 'hi', '2': 'there', '3': 'bla'}

And output

string.replace('@@@', '{}', len(kv)).format(*kv.values())
#Out: 'asfd hi fdsfd there ffds bla asdf'

Advantage of this solution: No explicit looping (explicit looping is almost always a bad idea in python) and only one line of code. Furthermore this is also working when the number of '@@@' is less **or greater than the number of values in kv**, when the count parameter in str.replace is specified.


This leads to the final and 99% failsafe variant of my solution, using the len of the dict as count argument in replace:

string.replace('@@@', '{}', len(kv)).format(*kv.values())
Sign up to request clarification or add additional context in comments.

4 Comments

For a fixed number of @ this should be the accepted solution (+1).
this is great! I only needed to modify the key in dictionary from string to int ('1' vs 1) to make it work properly, as string was messing up the order but string.replace('@@@', '{}', len(kv)).format(*kv.values()) was what I was looking for. Thanks!
You are welcome! What python version do you use? <=3.5? If you update to 3.6+, dicts will be ordered by creation order, meaning that the key does not influence the order.
Just remember that dicts will be ordered when updating to 3.6+, thus some results without explicitly selecting values by keys may change.
3

This is one approach using str.replace with optional parameter count.

Ex:

s = 'asfd @@@ fdsfd @@@ ffds @@@ asdf'
kv = {'1': 'hi', '2': 'there', '3': 'bla'}

for k, v in sorted(kv.items()):
    s = s.replace("@@@", v, 1)
print(s)

MoreInfo

Comments

3

You can use re.sub to get the job done with out any sorting

Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl. If the pattern isn’t found, string is returned unchanged. repl can be a string or a function; if it is a string, any backslash escapes in it are processed.

import re
string = 'asfd @@@ fdsfd @@@ ffds @@@ asdf'
kv = {'1': 'hi', '2': 'there', '3': 'bla'}
class repl:
    def __init__(self):
        self.called=0
    def __call__(self,match):
        self.called+=1
        return kv[str(self.called)]
print(re.sub('@@@',repl(),string))

OUTPUT

asfd hi fdsfd there ffds bla asdf

Comments

0
string = 'asfd @@@ fdsfd @@@ ffds @@@ asdf'
kv = {1: 'hi', 2: 'there', 3: 'bla'}

for k,v in kv.items():
    string = string.replace('@@@', v, 1)
print(string)

OUTPUT:

asfd hi fdsfd there ffds bla asdf

Comments

0
kv = {'1': 'hi', '2': 'there', '3': 'bla'}
string = 'asfd @@@ fdsfd @@@ ffds @@@ asdf'
string_list=string.split('@@@')
string_list_out=[]
for i in range(len(string_list)):
    if i==0:
        string_list_out.append(string_list[0])
    else:
        string_list_out.append(kv[str(i)])
        string_list_out.append(string_list[i])

string_list_out=''.join(string_list_out)
print(string_list_out)
   'asfd hi fdsfd there ffds bla asdf'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.