How to replace two things at once in a string?

Question:

Say I have a string, "ab".

I want to replace "a" with "b" and "b" with "a" in one swoop.

So in the end, the string should be "ba" and not "aa" or "bb" and not use more than one line. Is this doable?

Asked By: WhatsInAName

||

Answers:

import string
"abaababb".translate(string.maketrans("ab", "ba"))
# result: 'babbabaa'

Note that this only works for one-character substitutions.

For longer substrings or substitutions, this is a bit complex, but might work:

import re

def replace_all(repls, str):
    # return re.sub('|'.join(repls.keys()), lambda k: repls[k.group(0)], str)                                     
    return re.sub('|'.join(re.escape(key) for key in repls.keys()),
                  lambda k: repls[k.group(0)], str)                                     


text =  "i like apples, but pears scare me"
print replace_all({"apple": "pear", "pear": "apple"}, text)

Unfortunately this won’t work if you include any regexp special characters you can’t use regexps this way 🙁

(Thanks @TimPietzcker)

Answered By: Amadan
the_string="ab"
new_string=""

for x in range(len(the_string)):
    if the_string[x]=='a':
        new_string+='b'
        continue
    if the_string[x]=='b':
        new_string+='a'
        continue
    new_string+=the_string[x]

the_string=new_string

print the_string

If you are OK with two lines, this is more elegant.

d={'a':'b','b':'a'}
''.join(d[s] for s in "abaababbd" if s in d.keys())
Answered By: Abhijit

Your example is a little bit abstract but in the past I’ve used this recipe which builds a regular expression to do single-pass multiple replace. Here’s my tweaked version of it:

import re 

def multiple_replace(dict, text): 
  regex = re.compile("|".join(map(re.escape, dict.keys())))
  return regex.sub(lambda mo: dict[mo.group(0)], text) 

Note that the keys (searchstrings) are re.escaped.

In your case it would be:

from utils import multiple_replace

print multiple_replace({
    "a": "b",
    "b": "a"
}, "ab") 

UPDATE:

By now this is basically the same as Amadan’s answer

Answered By: Bruce van der Kooij
>>> import re
>>> re.sub('.', lambda m: {'a':'b', 'b':'a'}.get(m.group(), m.group()), 'abc')
'bac'
Answered By: kev

When you need to swap variables, say x and y, a common pattern is to introduce a temporary variable t to help with the swap: t = x; x = y; y = t.

The same pattern can also be used with strings:

>>> # swap a with b
>>> 'obama'.replace('a', '%temp%').replace('b', 'a').replace('%temp%', 'b')
'oabmb'

This technique isn’t new. It is described in PEP 378 as a way to convert between American and European style decimal separators and thousands separators (for example from 1,234,567.89 to 1.234.567,89. Guido has endorsed this as a reasonable technique.

Answered By: Raymond Hettinger
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.