1

I am trying to print out a custom format but am facing an issue.

header = ['string', 'longer string', 'str']
header1, header2, header3 = header
data = ['string', 'str', 'longest string']
data1, data2, data3 = data
len1 = len(header1)
len2 = len(header2)
len3 = len(header3)
len_1 = len(data1)
len_2 = len(data2)
len_3 = len(data3)
un = len1 + len2 + len3 + len_1 + len_2 + len_3
un_c = '_' * un
print(f"{un_c}\n|{header1} |{header2} |{header3}| \n |{data1} |{data2} |{data3}|")

Output:

_____________________________________________
|string |longer string |str|
 |string |str |longest string|

The output I want is this:

_______________________________________
|string |longer string |str           |
|string |str           |longest string|

I want it to work for all lengths of strings using the len to add extra spacing to each string to make it aligned, but I can't figure it out at all.

2
  • Use \t instead of spaces for proper spacing. Also, remove the space after newline so that the starting point of second line is not messed up Commented Jul 6, 2022 at 23:43
  • \t is not always the right solution. In his example, the string lengths vary by more than 8 characters. Commented Jul 6, 2022 at 23:52

4 Answers 4

2

There is a package called tabulate this is very good for this (https://pypi.org/project/tabulate/). Similar post here.

Sign up to request clarification or add additional context in comments.

Comments

1

Each cell is constructed according to the longest content, with additional spaces for any shortfall, printing a | at the beginning of each line, and the rest of the | is constructed using the end parameter of print

The content is placed in a nested list to facilitate looping, other ways of doing this are possible, the principle is the same and adding some content does not affect it

items = [
    ['string', 'longer string', 'str'],
    ['string', 'str', 'longest string'],
    ['longer string', 'str', 'longest string'],
]
length = [max([len(item[i]) for item in items]) for i in range(len(items[0]))]
max_length = sum(length)

print("_" * (max_length + 4))
for item in items:
    print("|", end="")
    for i in range(len(length)):
        item_length = len(item[i])

        if length[i] > len(item[i]):
            print(item[i] + " " * (length[i] - item_length), end="|")
        else:
            print(item[i], end="|")
    print()

OUTPUT:

____________________________________________
|string       |longer string|str           |
|string       |str          |longest string|
|longer string|str          |longest string|

Comments

1

Do it in two parts. First, figure out the size of each column. Then, do the printing based on those sizes.

header = ['string','longer string','str']
data = ['string','str','longest string']
lines = [header] * 3 + [data] * 3

def getsizes(lines):
    maxn = [0] * len(lines[0])
    for row in lines:
        for i,col in enumerate(row):
            maxn[i] = max(maxn[i], len(col)+1)
    return maxn

def maketable(lines):
    sizes = getsizes(lines)
    all = sum(sizes)
    print('_'*(all+len(sizes)) )
    for row in lines:
        print('|',end='')
        for width, col in zip( sizes, row ):
            print( col.ljust(width), end='|' )
        print()

maketable(lines)

Output:

_______________________________________
|string |longer string |str            |
|string |longer string |str            |
|string |longer string |str            |
|string |str           |longest string |
|string |str           |longest string |
|string |str           |longest string |

You could change it to build up a single string, if you need that.

Comments

1

It accept an arbitrary number of rows. Supposed each row has string-type terms.

def table(*rows, padding=2, sep='|'):
    sep_middle = ' '*(padding//2) + sep + ' '*(padding//2)
    template = '{{:{}}}'

    col_sizes = [max(map(len, col)) for col in zip(*rows)]

    table_template = sep_middle.join(map(template.format, col_sizes))

    print('_' * (sum(col_sizes) + len(sep_middle)*(len(header)-1) + 2*len(sep) + 2*(len(sep)*padding//2)))
    for line in (header, *rows):
        print(sep + ' ' * (padding//2) + table_template.format(*line) + ' ' * (padding//2) + sep)


header = ['string', 'longer string', 'str', '21']
data1 = ['string', 'str', 'longest stringhfykhj', 'null']
data2 = ['this', 'is', 'a', 'test']

# test 1
table(header, data1, data2)

# test 2
table(header, data1, data2, padding=4, sep=':')

Output

# first test
________________________________________________________
| string | longer string | str                  | 21   |
| string | longer string | str                  | 21   |
| string | str           | longest stringhfykhj | null |
| this   | is            | a                    | test |

# second test
________________________________________________________________
:  string  :  longer string  :  str                   :  21    :
:  string  :  longer string  :  str                   :  21    :
:  string  :  str            :  longest stringhfykhj  :  null  :
:  this    :  is             :  a                     :  test  :

Comments

Your Answer

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