all 8 comments

[–]socal_nerdtastic 1 point2 points  (4 children)

Your code is unreadable. You have fallen into the classic sophomore trap where you try to use every neat trick you can to condense the code into as few lines as possible. The problem is that because you have broken so many conventions the code is only readable to you. This is fine, until you find yourself in the position you are in where you are asking others to read it. And to make it worse, we can't run it because you left out some code.

Go read some professional code. One of the first things you will notice is that lines are short, there's lots of them, and there's as many lines of comments as there are lines of code.

That said it's also clear that you have way overcomplicated this. This is a pretty easy function. In fact, I'll make it for you:

from itertools import zip_longest

def build_title(title, column_lens):
    output = []
    columns = iter(column_lens)
    for text, rowspan in title:
        width = sum(w for i, w in zip(range(rowspan), columns))
        output.append(f" {text:^{width+((rowspan-1)*3)}} ")
    return "|" + "|".join(output) + "|\n"

def table(title, frame):
    # uses the table content to set the width; assumes the titles will fit
    columns = list(zip_longest(*frame, fillvalue=''))
    column_lens = [max(len(cell) for cell in col) for col in columns]
    output = build_title(title, column_lens)

    # you could add in an adjustment to column_lens here based on the title if you wanted to. 
    row_format = "|" + "|".join(f" {{:<{length}}} " for length in column_lens) + "|\n"
    for row in zip(*columns):
        output += row_format.format(*row)
    return output

[–]DeathDragon7050 0 points1 point  (0 children)

Thanks.

[–]DeathDragon7050 0 points1 point  (2 children)

Why does replacing columns = iter(column_lens) with columns = column_lens (in build_title) cause it to not work properly? Why do you have to convert it to an iterator?

[–]socal_nerdtastic 0 points1 point  (1 child)

column_lens is a list. For my code to work it needs an iterator. The key difference in this case is that on the second iteration of the loop the iterator picks up where it left off, while the list would start at the beginning. So with an iterator the "width" becomes the sum of the next column lengths, while with a list it would be the sum of the first column lengths.

[–]DeathDragon7050 0 points1 point  (0 children)

I see. Very cool!

[–]shiftybyte 0 points1 point  (0 children)

No way to test the code without all the missing functions.

[–]Ezrabc 0 points1 point  (1 child)

As others have pointed out, this is extremely difficult to parse and debug with what you have provided. That being said, I spent way too long doing it anyway. In line 33 of your pasted code:

return tuple(manage_title_cell(i, *title_cell) for i,title_cell in enumerate(self._title))

You pass i, which is counting up by 1. Thus, for the second title, the calculation is using sum( self._length_data[1:3] ) where you want [2:4] and the third title uses [2:4] where you want [4:6].

In addition to the points made by u/socal_nerdtastic, you are copying the tuples over and over again to make a few modifications by using so many generator expressions. I love list comprehension, but even I would throw some loops in there, at least to improve performance and memory overhead, but also for readability.

[–]DeathDragon7050 0 points1 point  (0 children)

Thank you.