Most pythonic way to interleave two strings

StackOverflow

What"s the most pythonic way to mesh two strings together?

For example:

Input:

u = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
l = "abcdefghijklmnopqrstuvwxyz"

Output:

"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"

Answer rating: 127

For me, the most pythonic* way is the following which pretty much does the same thing but uses the + operator for concatenating the individual characters in each string:

res = "".join(i + j for i, j in zip(u, l))
print(res)
# "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"

It is also faster than using two join() calls:

In [5]: l1 = "A" * 1000000; l2 = "a" * 1000000

In [6]: %timeit "".join("".join(item) for item in zip(l1, l2))
1 loops, best of 3: 442 ms per loop

In [7]: %timeit "".join(i + j for i, j in zip(l1, l2))
1 loops, best of 3: 360 ms per loop

Faster approaches exist, but they often obfuscate the code.

Note: If the two input strings are not the same length then the longer one will be truncated as zip stops iterating at the end of the shorter string. In this case instead of zip one should use zip_longest (izip_longest in Python 2) from the itertools module to ensure that both strings are fully exhausted.


*To take a quote from the Zen of Python: Readability counts.
Pythonic = readability for me; i + j is just visually parsed more easily, at least for my eyes.

Answer rating: 63




Faster Alternative

Another way:

res = [""] * len(u) * 2
res[::2] = u
res[1::2] = l
print("".join(res))

Output:

"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"



Speed

Looks like it is faster:

%%timeit
res = [""] * len(u) * 2
res[::2] = u
res[1::2] = l
"".join(res)

100000 loops, best of 3: 4.75 µs per loop

than the fastest solution so far:

%timeit "".join(list(chain.from_iterable(zip(u, l))))

100000 loops, best of 3: 6.52 µs per loop

Also for the larger strings:

l1 = "A" * 1000000; l2 = "a" * 1000000

%timeit "".join(list(chain.from_iterable(zip(l1, l2))))
1 loops, best of 3: 151 ms per loop


%%timeit
res = [""] * len(l1) * 2
res[::2] = l1
res[1::2] = l2
"".join(res)

10 loops, best of 3: 92 ms per loop

Python 3.5.1.




Variation for strings with different lengths

u = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
l = "abcdefghijkl"

Shorter one determines length (zip() equivalent)

min_len = min(len(u), len(l))
res = [""] * min_len * 2 
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
print("".join(res))

Output:

AaBbCcDdEeFfGgHhIiJjKkLl

Longer one determines length (itertools.zip_longest(fillvalue="") equivalent)

min_len = min(len(u), len(l))
res = [""] * min_len * 2 
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
res += u[min_len:] + l[min_len:]
print("".join(res))

Output:

AaBbCcDdEeFfGgHhIiJjKkLlMNOPQRSTUVWXYZ




Get Solution for free from DataCamp guru