4

How do I take the first character from each string in a list, join them together, then the second character from each string, join them together, and so on - and eventually create one combined string?

eg. if I have strings like these:

homanif
eiesdnt
ltiwege
lsworar

I want the end result to be helloitsmeiwaswonderingafter

I put together a very hackneyed version of this which does the job but produces an extra line of gibberish. Considering this is prone to index going out of range, I don't think this is a good approach:

final_c = ['homanif', 'eiesdnt', 'ltiwege', 'lsworar']

final_message = ""
current_char = 0

for i in range(len(final_c[1])):
    for c in final_c:
        final_message += c[current_char]
    current_char += 1

final_message += final_c[0][:-1]    

print(final_message)    

gives me helloitsmeiwaswonderingafterhomani when it should simply stop at helloitsmeiwaswonderingafter.

How do I improve this?

2
  • 3
    ''.join(''.join(t) for t in (zip(*final_c))) Commented Feb 13, 2019 at 12:42
  • @Chris_Rands your solution worked great! I wish I could mark it as the answer. Commented Feb 13, 2019 at 13:29

5 Answers 5

3

Problems related to iterating in some convoluted order can often be solved elegantly with itertools.

Using zip

You can use zip and itertools.chain together.

from itertools import chain

final_c = ['homanif', 'eiesdnt', 'ltiwege', 'lsworar']
final_message = ''.join(chain.from_iterable(zip(*final_c))) # 'helloitsmeiwaswonderingafter'

In the event you needed the strings in final_c to be of different lengths, you could tweak your code a bit by using itertools.zip_longest.

final_message = ''.join(filter(None, chain.from_iterable(zip_longest(*final_c))))

Using cycle

The fun part with itertools is that it offers plenty of clever short solutions for iterating over objects. Here is another using itertools.cycle.

from itertools import cycle

final_c = ['homanif', 'eiesdnt', 'ltiwege', 'lsworara']
final_message = ''.join(next(w) for w in cycle(iter(w) for w in final_c))
Sign up to request clarification or add additional context in comments.

Comments

2

You can use a nested comprehension:

x = ["homanif", 
     "eiesdnt", 
     "ltiwege", 
     "lsworar"] 

y = "".join(x[i][j]
            for j in range(len(x[0]))
            for i in range(len(x)))

or use nested joins and zip

y = "".join("".join(y) for y in zip(*x))     

1 Comment

@Chris_Rands already gave me the second one-liner code in the comments section instead, which worked really well. Nonetheless, I'll mark this as the correct answer since it has that. Thanks!
1

Here is a code that works for me :

final_c = ["homanif", "eiesdnt", "ltiwege", "lsworar"]
final_message = ""
current_char = 0

for i in range(len(final_c[1])):
    for c in final_c:
        final_message += c[current_char]
    current_char += 1

# final_message += final_c[0][:-1]    

print(final_message) 

I hope it helps

Comments

1

I don't understand what you are expecting with the line final_message += final_c[0][:-1]

The code works just fine without that. Either remove that line or go with something like list comprehensions :

final_message = "".join(final_c[i][j] for j in range(len(final_c[0])) for i in range(len(final_c)))

This gives the expected output:

helloitsmeiwaswonderingafter

Comments

0

looks like you can have a matrix of form nxm where n is the number of words and m is the number of character in a word (the following code will work if all your words have the same length)

import numpy as np

n = len(final_c)  # number of words in your list
m = len(final_c[0])  # number of character in a word

array = np_array(''.join([list(w) for w in ''.join(final_c)])
# reshape the array 
matrix = array.reshape(n,1,m )
''.join(matrix.transpose().flatten())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.