Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

356
Views
Python best way to 'swap' words (multiple characters) in a string?

Consider the following examples:

string_now = 'apple and avocado'
stringthen = string_now.swap('apple', 'avocado') # stringthen = 'avocado and apple'

and:

string_now = 'fffffeeeeeddffee'
stringthen = string_now.swap('fffff', 'eeeee') # stringthen = 'eeeeefffffddffee'

Approaches discussed in Swap character of string in Python do not work, as the mapping technique used there only takes one character into consideration. Python's builtin str.maketrans() also only supports one-character translations, as when I try to do multiple characters, it throws the following error:

enter image description here

A chain of replace() methods is not only far from ideal (since I have many replacements to do, chaining replaces would be a big chunk of code) but because of its sequential nature, it will not translate things perfectly as:

string_now = 'apple and avocado'
stringthen = string_now.replace('apple','avocado').replace('avocado','apple')

gives 'apple and apple' instead of 'avocado and apple'.

What's the best way to achieve this?

over 4 years ago · Santiago Trujillo
5 answers
Answer question

0

I managed to make this function that does exactly what you want.

def swapwords(mystr, firstword, secondword):
    splitstr = mystr.split(" ")

    for i in range(len(splitstr)):
        if splitstr[i] == firstword:
            splitstr[i] = secondword
            i+=1
        if splitstr[i] == secondword:
            splitstr[i] = firstword
            i+=1

    newstr = " ".join(splitstr)

   return newstr

Basically, what this does is it takes in your string "Apples and Avacados", and splits it by spaces. Thus, each word gets indexed in an array splitstr[]. Using this, we can use a for loop to swap the words. The i+=1 is in order to ensure the words don't get swapped twice. Lastly, I join the string back using newstr= " ".join(splitstr) which joins the words separated by a space.

Running the following code gives us: Avacados and Apples.

over 4 years ago · Santiago Trujillo Report

0

Given that we want to swap words x and y, and that we don't care about the situation where they overlap, we can:

  • split the string on occurrences of x
  • within each piece, replace y with x
  • join the pieces with y

Essentially, we use split points within the string as a temporary marker to avoid the problem with sequential replacements.

Thus:

def swap_words(s, x, y):
    return y.join(part.replace(y, x) for part in s.split(x))

Test it:

>>> swap_words('apples and avocados and avocados and apples', 'apples', 'avocados')
'avocados and apples and apples and avocados'
>>>
over 4 years ago · Santiago Trujillo Report

0

Two regex solutions and one for other people who do have a character that can't appear (there are over a million different possible characters, after all) and who don't dislike replace chains :-)

def swap_words_regex1(s, x, y):
    return re.sub(re.escape(x) + '|' + re.escape(y),
                  lambda m: (x if m[0] == y else y),
                  s)

def swap_words_regex2(s, x, y):
    return re.sub(f'({re.escape(x)})|{re.escape(y)}',
                  lambda m: x if m[1] is None else y,
                  s)

def swap_words_replaces(s, x, y):
    return s.replace(x, chr(0)).replace(y, x).replace(chr(0), y)

Some benchmark results:

 3.7 ms  1966 kB  swap_words_split
10.7 ms  2121 kB  swap_words_regex1
17.8 ms  2121 kB  swap_words_regex2
 1.3 ms   890 kB  swap_words_replaces

Full code (Try it online!):

from timeit import repeat
import re
import tracemalloc as tm

def swap_words_split(s, x, y):
    return y.join(part.replace(y, x) for part in s.split(x))

def swap_words_regex1(s, x, y):
    return re.sub(re.escape(x) + '|' + re.escape(y),
                  lambda m: (x if m[0] == y else y),
                  s)

def swap_words_regex2(s, x, y):
    return re.sub(f'({re.escape(x)})|{re.escape(y)}',
                  lambda m: x if m[1] is None else y,
                  s)

def swap_words_replaces(s, x, y):
    return s.replace(x, chr(0)).replace(y, x).replace(chr(0), y)

funcs = swap_words_split, swap_words_regex1, swap_words_regex2, swap_words_replaces

args = 'apples and avocados and bananas and oranges and ' * 10000, 'apples', 'avocados'

for _ in range(3):
    for func in funcs:
        t = min(repeat(lambda: func(*args), number=1))
        tm.start()
        func(*args)
        memory = tm.get_traced_memory()[1]
        tm.stop()
        print(f'{t * 1e3:4.1f} ms  {memory // 1000:4} kB  {func.__name__}')
    print()
over 4 years ago · Santiago Trujillo Report

0

Why not just use a temp string which will never be in the origin string?

for example:

>>> a = 'apples and avocados and avocados and apples'
>>> b = a.replace('apples', '#IamYourFather#').replace('avocados', 'apples').replace('#IamYourFather#', 'avocados')
>>> print(b)
avocados and apples and apples and avocados

where #IamYourFather# is a string which will never be in the origin string.

over 4 years ago · Santiago Trujillo Report

0

This solution uses str.format():

string_now = "apple and avocado"
stringthen = (  # "avocado and apple"
    string_now.replace("apple", "{apple}")
    .replace("avocado", "{avocado}")
    .format(apple="avocado", avocado="apple")
)

# Edit: as a function
def swap_words(s, x, y):
    return s.replace(x, "{" + x + "}")
            .replace(y, "{" + y + "}")
            .format(**{x: y, y: x})

It first adds curly brackets before and after keywords to turn them into placeholders. Then str.format() is used to replace the placeholders.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!