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?


Solution 1:

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)

Solution 2:

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'

Solution 3:

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'
>>>

Solution 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

Solution 5:

''.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.