ascii tables

John Hunter jdhunter at ace.bsd.uchicago.edu
Mon Jun 2 12:28:57 EDT 2003


>>>>> "Carel" == Carel Fellinger <carel.fellinger at chello.nl> writes:

    Carel> it's old printer wisdom that one should be very reluctant
    Carel> to use lines in tables, and indeed I find the following
    Carel> much easier on the eyes:

I agree, I modified ascii_table to take a '' argument for rowSep,
which prints the table as you suggested, and added a repeatHeader
entry to allow you to repeat the header every so many lines for long
tables.  I also added headerColSep and headerRowSep variables so that
the separator for headers and regular rows can be different, with
default values making them the same.

    Carel> you could also use str's center, ljust and rjust methods.

Another good suggestion, implemented below.

The code below, with suitable args, now prints:

Name    :  Age : Sex  :  Weight :  Height
*****************************************
John        35    M       170.0      60.1
Miriam      31    F       135.0      58.2
Rahel        5    F        40.0      48.2
Ava          2    F        25.0      30.0

  
Thanks,
John Hunter

def ascii_table(headers, cols, fmts, alignments=None,
                rowSep='-', colSep='|', pad=1,
                headerRowSep=None,
                headerColSep=None,
                repeatHeader=0):
    """
    Pretty print the homogenous lists in cols.

    headers is a len(columns) tuple of header strings.
    cols is a len(columns) tuple of homogeneous lists (len num rows)
    fmts is a len(columns) tuple of format strings.
    alignments, if not None, is a list of horiz alignment strings:
                 'l' or 'r' or 'c'.  Default is 'l'


    repeatHeader, if not 0, will repeat the header every repeatHeader
          rows

    rowSep is used to join the rows; ifis '', rows will be joined with a newline alone

    colSep is used to join the columns
    
    headerRowSep is used to separate the headers from the other rows.
        If None, just use rowSep

    headerColSep is used to separate the header columns.  If None,
       just use colSep
    

    Example usage:

    headers = 'Name', 'Age', 'Sex', 'Weight', 'Height'
    names = 'John', 'Miriam', 'Rahel', 'Ava'
    ages = 35, 31, 5, 2
    sexes = 'M', 'F', 'F', 'F'
    weights  = 170, 135, 40, 25
    heights  = 60.1, 58.2, 48.2, 30

    print ascii_table(headers,
                      cols = (names, ages, sexes, weights, heights),
                      fmts = ('%s', '%d', '%s', '%1.1f', '%1.1f'),
                      alignments = ('l', 'r', 'c', 'r', 'r'),
                      )

    """
    
    if alignments is None:
        alignments = ['l']*len(cols)

    if headerColSep is None: headerColSep = colSep
    colSepWid = max(len(colSep), len(headerColSep))
    colSep = ' '*pad + colSep + ' '*pad
    headerColSep = ' '*pad + headerColSep + ' '*pad

    
    def pad_entry(entry, align, width):

        if align=='l': return entry.ljust(width)
        elif align=='r': return entry.rjust(width)
        else: return entry.center(width)

    colStrs = []
    headerStrs = []
    widths = []
    
    for col,fmt,header,align in zip(cols, fmts, headers, alignments):

        entries = [fmt % val for val in col]
        width = max(len(header), max(map(len, entries))) + colSepWid
        colStrs.append([pad_entry(entry, align, width)
                        for entry in entries])
        headerStrs.append( pad_entry(header, align, width) )




    lines = [colSep.join(tup) for tup in zip(*colStrs)]
    header = headerColSep.join(headerStrs)
    maxLen = max(len(header), max(map(len, lines)))

    if rowSep is '':  rowSep = '\n'
    else: rowSep = '\n' + rowSep*maxLen + '\n'

    if headerRowSep is None: headerRowSep = rowSep
    else: headerRowSep = '\n' + headerRowSep*maxLen + '\n'


    s = header + headerRowSep
    for i,line in enumerate(lines):
       if repeatHeader and i>0 and i%repeatHeader==0:
          s += '\n' + header + headerRowSep           
       s += line + rowSep
    return s

if __name__=='__main__':
   headers = 'Name', 'Age', 'Sex', 'Weight', 'Height'
   names = 'John', 'Miriam', 'Rahel', 'Ava'
   ages = 35, 31, 5, 2
   sexes = 'M', 'F', 'F', 'F'
   weights  = 170, 135, 40, 25
   heights  = 60.1, 58.2, 48.2, 30

   print ascii_table(headers,
                     cols = (names, ages, sexes, weights, heights),
                     fmts = ('%s', '%d', '%s', '%1.1f', '%1.1f'),
                     alignments = ('l', 'r', 'c', 'r', 'r'),
                     repeatHeader=0,
                     rowSep='',
                     colSep=' ',
                     headerRowSep = '*',
                     headerColSep = ':',
                     pad=1,
                     )





More information about the Python-list mailing list