Search code examples
pythonpython-3.xpretty-print

print different column widths in python


Im using python 3 here without importing pandas, trying to neat print an output of a list. It must have varying column widths. E.g. max length of word in column +2. I have a neat output thus far but all columns in all rows have the same spacing. spacing = max length of word.

Here is what I have: the list is read in from a csv and formatted into the below list labelled list.

list = [['0', 'Name', 'at', 'Address', '11111', 'Pl'], ['1', 'Name', 'at', 'Address', '36', 'Crt'],['2', 'Name', 'at', 'Address', '5678', 'cl'],['3', 'Name', 'at', 'Address', '7', 'St'],['']]

col_width = max(len(word) for row in list for word in row) + 2   # padding of 2

for row in list :

     print "".join(word.ljust(col_width) for word in row)

output:

0      Name      at      Address      11111      Pl
1      Name      at      Address      36         Crt
2      Name      at      Address      5678       cl
3      Name      at      Address      7          St

Preferred output:

0. Name   at Address   11111 Pl
1. Name   at Address   36    Crt
2. Name   at Address   5678  cl
3. Name   at Address   7     St

I have changed the rows to columns and it still made no difference. My apologies but what am I not understanding here? Thank you for your time.


Solution

  • You're currently using the maximum length of any word in your data instead of maximum length in given column. You need to calculate the max width for each column and use that instead.

    In order to do that you can feed the data to itertools.zip_longest to get data column by column and store the max width for each column. Then when you're outputting the data just pass respective width to ljust:

    from itertools import zip_longest
    
    l = [['0', 'Name', 'at', 'Address', '11111', 'Pl'],
         ['1', 'Name', 'at', 'Address', '36', 'Crt'],
         ['2', 'Name', 'at', 'Address', '5678', 'cl'],
         ['3', 'Name', 'at', 'Address', '7', 'St'],['']]
    
    widths = [max(len(s) for s in x) for x in zip_longest(*l, fillvalue='')]
    
    for row in l :
        print("".join(word.ljust(w + 2) for word, w in zip(row, widths)))
    

    Output:

    0  Name  at  Address  11111  Pl
    1  Name  at  Address  36     Crt
    2  Name  at  Address  5678   cl
    3  Name  at  Address  7      St
    

    Update: Assuming that all the rows have same amount of columns and you want have varied padding you can use zip and create a dict that overrides the padding for some columns:

    DEFAULT = 2
    l = [['0', 'Name', 'at', 'Address', '11111', 'Pl'],
         ['1', 'Name', 'at', 'Address', '36', 'Crt'],
         ['2', 'Name', 'at', 'Address', '5678', 'cl'],
         ['3', 'Name', 'at', 'Address', '7', 'St']]
    
    padding = {2: 1}
    widths = [max(len(s) for s in x) for x in zip(*l)]
    
    for row in l :
        print("".join(word.ljust(w + padding.get(i, DEFAULT))
                      for i, (word, w) in enumerate(zip(row, widths))))
    

    Output:

    0  Name  at Address  11111  Pl
    1  Name  at Address  36     Crt
    2  Name  at Address  5678   cl
    3  Name  at Address  7      St