# Join strings split with the python [::n] method into one string as they were before in one line

If you split a string like foobar with something like [::3], [1::3], [2::3] it will give you ['fb','oa','or']. I needed to then be able to rejoin that into foobar and I got given a challenge to make it in one line. This is my solution:

split_join = lambda t:''.join(''.join([s.ljust(len(max(t,key=len))) for s in t])[i::len(max(t,key=len))] for i in range(len(max(t,key=len)))).replace(' ','')


and I was wondering if there was any neater or shorter way to make this.

EDIT: I also want it to be able to deal with strings of uneven lengths

## 2 Answers

First, in order to make this even remotely readable, let's convert it to a function and save intermediate results (especially the reused ones) to variables:

def split_join6(table):
cols = max(map(len, table))
justified = ''.join([col.ljust(cols) for col in table])
y = ''.join(justified[i::cols] for i in range(cols))
return y.replace(' ','')


Now, what you seem to want is similar to the roundrobin recipe from itertools:

from itertools import cycle, islice

def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
num_active = len(iterables)
nexts = cycle(iter(it).__next__ for it in iterables)
while num_active:
try:
for next in nexts:
yield next()
except StopIteration:
# Remove the iterator we just exhausted from the cycle.
num_active -= 1
nexts = cycle(islice(nexts, num_active))

x = ['fb','oa','or']
print("".join(roundrobin(*x))
# foobar


Note that making things into one-liners can only get you so far. It does sometimes help you to learn some new concepts in a language, but quite often it makes your code unreadable. In Python you should keep your lines to 80 or 120 characters (as per Python's official style-guide, PEP8). Anything that does not fit into that is probably too complicated to understand again, even a month later.

That being said, here is a shorter one-liner, albeit with one needed import:

from itertools import zip_longest

f = lambda x: "".join(map(lambda t: "".join(filter(None, t)), zip_longest(*x)))

f(['fb','oa','or'])
# 'foobar'


The zip_longest and filter(None, ...) are only needed in case not all parts are the same length. Otherwise (which is at least true for "foobar") it would just be:

f = lambda x: "".join(map("".join, zip(*x)))


Both use the well-known trick of doing zip(*iterable) to transpose an iterable of iterables.

• Thanks you for bringing my attention to the zip function, really neat – 13ros27 Nov 27 '18 at 15:56

Using what @Graipher said and some other things I found my new solution is:

split_join = lambda t:''.join(sum(zip(*[s.ljust(len(max(t,key=len))) for s in t]),())).replace(' ','')


If I find any better way I will update this code