# What is the simplest way to swap each pair of adjoining chars in a string with Python?

Posted on

### Question :

What is the simplest way to swap each pair of adjoining chars in a string with Python?

I want to swap each pair of characters in a string. `'2143'` becomes `'1234'`, `'badcfe'` becomes `'abcdef'`.

How can I do this in Python?

oneliner:

``````>>> s = 'badcfe'
>>> ''.join([ s[x:x+2][::-1] for x in range(0, len(s), 2) ])
'abcdef'
``````
• s[x:x+2] returns string slice from x to x+2; it is safe for odd len(s).
• [::-1] reverses the string in Python
• range(0, len(s), 2) returns 0, 2, 4, 6 … while x < len(s)

The usual way to swap two items in Python is:

``````a, b = b, a
``````

So it would seem to me that you would just do the same with an extended slice. However, it is slightly complicated because strings aren’t mutable; so you have to convert to a list and then back to a string.
Therefore, I would do the following:

``````>>> s = 'badcfe'
>>> t = list(s)
>>> t[::2], t[1::2] = t[1::2], t[::2]
>>> ''.join(t)
'abcdef'
``````

Here’s one way…

``````>>> s = '2134'
>>> def swap(c, i, j):
...  c = list(c)
...  c[i], c[j] = c[j], c[i]
...  return ''.join(c)
...
>>> swap(s, 0, 1)
'1234'
>>>
``````

Loop over length of string by twos and swap:

``````def oddswap(st):
s = list(st)
for c in range(0,len(s),2):
t=s[c]
s[c]=s[c+1]
s[c+1]=t

return "".join(s)
``````

giving:

``````>>> s
'foobar'
>>> oddswap(s)
'ofbora'
``````

and fails on odd-length strings with an IndexError exception.

``````''.join(s[i+1]+s[i] for i in range(0, len(s), 2)) # 10.6 usec per loop
``````

or

``````''.join(x+y for x, y in zip(s[1::2], s[::2])) # 10.3 usec per loop
``````

or if the string can have an odd length:

``````''.join(x+y for x, y in itertools.izip_longest(s[1::2], s[::2], fillvalue=''))
``````

Note that this won’t work with old versions of Python (if I’m not mistaking older than 2.5).

The benchmark was run on python-2.7-8.fc14.1.x86_64 and a Core 2 Duo 6400 CPU with `s='0123456789'*4`.

If performance or elegance is not an issue, and you just want clarity and have the job done then simply use this:

``````def swap(text, ch1, ch2):
text = text.replace(ch2, '!',)
text = text.replace(ch1, ch2)
text = text.replace('!', ch1)
return text
``````

This allows you to swap or simply replace chars or substring.
For example, to swap ‘ab’ <-> ‘de’ in a text:

``````_str = "abcdefabcdefabcdef"
print swap(_str, 'ab','de') #decabfdecabfdecabf
``````

There is no need to make a list. The following works for even-length strings:

``````r = ''
for in in range(0, len(s), 2) :
r += s[i + 1] + s[i]
s = r
``````

``````s = '2143'