How to insert a character after every 2 characters in a string

Viewed 54518

Is there a pythonic way to insert an element into every 2nd element in a string?

I have a string: 'aabbccdd' and I want the end result to be 'aa-bb-cc-dd'.

I am not sure how I would go about doing that.

7 Answers

I tend to rely on a regular expression for this, as it seems less verbose and is usually faster than all the alternatives. Aside from having to face down the conventional wisdom regarding regular expressions, I'm not sure there's a drawback.

>>> s = 'aabbccdd'
>>> '-'.join(re.findall('..', s))
'aa-bb-cc-dd'

This version is strict about actual pairs though:

>>> t = s + 'e'
>>> '-'.join(re.findall('..', t)) 
'aa-bb-cc-dd'

... so with a tweak you can be tolerant of odd-length strings:

>>> '-'.join(re.findall('..?', t))
'aa-bb-cc-dd-e'

Usually you're doing this more than once, so maybe get a head start by creating a shortcut ahead of time:

PAIRS = re.compile('..').findall

out = '-'.join(PAIRS(in))

Or what I would use in real code:

def rejoined(src, sep='-', _split=re.compile('..').findall):
    return sep.join(_split(src))

>>> rejoined('aabbccdd', sep=':')
'aa:bb:cc:dd'

I use something like this from time to time to create MAC address representations from 6-byte binary input:

>>> addr = b'\xdc\xf7\x09\x11\xa0\x49'
>>> rejoined(addr[::-1].hex(), sep=':')
'49:a0:11:09:f7:dc'

As PEP8 states:

Do not rely on CPython's efficient implementation of in-place string concatenation for statements in the form a += b or a = a + b. This optimization is fragile even in CPython (it only works for some types) and isn't present at all in implementations.

A pythonic way of doing this that avoids this kind of concatenation, and allows you to join iterables other than strings could be:

':'.join(f'{s[i:i+2]}' for i in range(0, len(s), 2))

And another more functional-like way could be:

':'.join(map('{}{}'.format, *(s[::2], s[1::2]))) 

This second approach has a particular feature (or bug) of only joining pairs of letters. So:

>>> s = 'abcdefghij'
'ab:cd:ef:gh:ij'

and:

>>> s = 'abcdefghi'
'ab:cd:ef:gh'
Related