PreacherBaby
PreacherBaby

Reputation: 23

Looking for a more "pythonic" solution for my practice task

everyone. While practicing strings I encountered a practice task that made me struggle with making my code look as simple as it can be.

The body of the task:

Write a function that transposes a list of strings, in which each string contains multiple words separated by whitespace. Specifically, it should perform in such a way that if you were to pass the list ['abc def ghi', 'jkl mno pqr', 'stu vwx yz'] to the function, it would return ['abc jkl stu', 'def mno vwx', 'ghi pqr yz'] .

My code:

old_list = ['abc def ghi', 'jkl mno pqr', 'stu vwx yz']
    
    def func(old_list):
        new_list = []
        sentence = ''.join(old_list)
        index_one = sentence[0:3] + ' ' + sentence[11:14] + ' ' + sentence[22:25]
        index_two = sentence[4:7] + ' ' + sentence[15:18] + ' ' + sentence[26:29]
        index_three = sentence[8:11] + ' ' + sentence[19:22] + ' ' + sentence[30:32]
        new_list.append(index_one)
        new_list.append(index_two)
        new_list.append(index_three)
        return new_list

it looks so "not good" even I can see that. How can I optimize it so it would look cleaner?

Upvotes: 0

Views: 414

Answers (3)

jorf.brunning
jorf.brunning

Reputation: 472

Let's break the problem into two parts:

  1. how do we transform a string to a list
  2. how do we slice and dice the lists to get your output

#1

Let's say we have the following strings, similar to yours.

>>> s1 = '1 2 3'
>>> s2 = '4 5 6'
>>> s3 = '7 8 9'

You can use .split() to split the text into a list by a delimiter (by default ' ')

>>> s1.split()
['1', '2', '3']

Let's do that for all our strings:

lists = [x.split() for x in [s1, s2, s3]]
>>> lists
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]

#2

How do we get the first element from all the lists, then the second, and so on?

We use zip: https://docs.python.org/3.3/library/functions.html#zip

>>> list(zip(*lists))
[('1', '4', '7'), ('2', '5', '8'), ('3', '6', '9')]

If your program wants you to display those as strings, and not a list of tuples:

>>> [" ".join(x) for x in zip(*lists)]
['1 4 7', '2 5 8', '3 6 9']

Upvotes: 5

Ibrahim Ahmed
Ibrahim Ahmed

Reputation: 11

you can try this code which utilizes the split method, and then loops through each list to concatenate the nth same element number of each list:

L = ['abc def ghi', 'jkl mno pqr', 'stu vwx yz']

def custom_L(L):
    #Assigning the Final List before looping
    Final = []
    #Splitting each string in the List
    for i in range(len(L)):
        L[i] = L[i].split()
    '''This basically says hey in i = 1 for example
     I want you to concatenate each first element 
     for each list inside L with ' ' in between as a seperator
     and the same for second and same for third'''
    for i in range(len(L)):
        Final += [' '.join([SubL[i] for SubL in L])]
    return Final


output = custom_L(L)
print(output)

Upvotes: 1

Crivella
Crivella

Reputation: 1007

You could make use of the split method of string objects for splitting the strings and than use numpy to transpose it

import numpy as np
old_list = ['abc def ghi', 'jkl mno pqr', 'stu vwx yz']

app = np.array([_.split(' ') for _ in old_list])

print(app.T)


# [['abc' 'jkl' 'stu']
#  ['def' 'mno' 'vwx']
#  ['ghi' 'pqr' 'yz']]

EDIT: for all the commenteres disparaging numpy and saying this can be done in one line (I think for a beginner this is much more difficult to look at)

print([' '.join(_) for _ in zip(*[_.split(' ') for _ in old_list])])
# ['abc jkl stu', 'def mno vwx', 'ghi pqr yz']

Upvotes: -1

Related Questions