Rearrange sections of text lines to columns for printing as table (Python)

Viewed 32

I want to rearrange sections of text into a text where these sections appear as columns.

Below the code I have came up with up to now:

sectSepar = '\n---\n'
mltiColmn = """\
Column A
first row
second row
3rd row
---
Column B
1. only
---
Column C
1. ...
2. long-long text"""

import itertools
print( *list(itertools.zip_longest(*[ 
   [ column.ljust(maxlen:=max(map(len, section.split('\n')))) 
       for column in section.split('\n') ]
           for section in mltiColmn.split(sectSepar) ],
           fillvalue=''.ljust(maxlen))),sep='\n')

The code works OK, but it prints:

('Column A  ', 'Column B', 'Column C         ')
('first row ', '1. only ', '1. ...           ')
('second row', '                 ', '2. long-long text')
('3rd row   ', '                 ', '                 ')

instead of

('Column A  ', 'Column B', 'Column C         ')
('first row ', '1. only ', '1. ...           ')
('second row', '        ', '2. long-long text')
('3rd row   ', '        ', '                 ')

I assume that the problem the code has is that Python evaluates the value of maxlen not as I would like it would do, but don't have an idea how to resolve the problem. Along with this I don't like the way the code is written as I am loosing the overview because of the nesting and hard to track brackets. So my question is:

Is there a way to write code for such text rearrangement that is easy to read and to understand (e.g. using chaining instead of nesting commands like max(map(len ...))) and which provides the right output?

1 Answers

To go issues with deep nested list comprehensions out of the way I suggest to split the rearrangement into steps as follows:

colmnsAsTxtLines = """\
Column A
first row
second row
3rd row
---
Column B
1. only
---
Column C
1. ...
2. long-long text"""
sectSepar = '\n---\n'

import itertools
Rows = list(itertools.zip_longest(*[ section.split('\n') 
       for section in colmnsAsTxtLines.split(sectSepar)],fillvalue=' '))
print( *[ list(e) for e in zip(*[list(map(str.ljust, sectnLines, 
        [max(map(len,sectnLines))]*len(sectnLines))) 
        for sectnLines in zip(*Rows) ] ) ], sep='\n')

the code above gives the right requested output:

['Column A  ', 'Column B', 'Column C         ']
['first row ', '1. only ', '1. ...           ']
['second row', '        ', '2. long-long text']
['3rd row   ', '        ', '                 ']
Related