ascii tables

John Hunter jdhunter at ace.bsd.uchicago.edu
Thu May 29 15:01:47 EDT 2003


>>>>> "Peter" == Peter Hansen <peter at engcorp.com> writes:

    Peter> John Hunter wrote:
    >>  I often need to print several equal length, homogeneous lists
    >> (some lists are strings, some ints, some floats), and I would
    >> like to make a nice ascii table for display, with configurable
    >> format strings for each column, row and column separators
    >> etc....  Anyone know of some code that does this?

    Peter> Not existing code, but it doesn't sound too hard.
    Peter> Here are some ideas (untested):

    Peter>     [ 'test', 55.6, 'a longer string' ]

The problem is that the lists are homogeneous, ie, all elements of the
same type. This arises a lot in my data analyses, where I may have an
array of heights, and array of weights, and array of names, etc, all
of the same length, and I want to pretty print them.  Sorry I wasn't
clearer in my original post.

Here is my first pass at a solution, which 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




def ascii_table(headers, cols, fmts, alignments=None,
                rowSep='-', colSep='|', pad=1):
    """
    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.
    fmts is a len(columns) tuple of format strings.
    alignments, if not None, is a a len(columns) tuple of horiz 
                 alignment strings: 'l' or 'r' or 'c'.  Default 'l'

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

    def pad_entry(entry, align, width):
        numSpaces = width-len(entry)-1 + pad

        if align=='l': return entry + ' '*numSpaces
        elif align=='r': return ' '*numSpaces + entry
        else: # align center 
            s =  ' '*(numSpaces/2) + entry + ' '*(numSpaces/2)
            if numSpaces % 2 == 1: s += ' '
            return s

    colStrs = []
    for col,fmt,header,align in zip(cols, fmts, headers, alignments):
        entries = [header]
        entries.extend([fmt % val for val in col])
        width = max(map(len, entries))
        colStrs.append([pad_entry(entry, align, width) for entry in entries])
        



    colSep = ' '*pad + colSep + ' '*pad

    lines = [colSep.join(tup) for tup in zip(*colStrs)]
    maxLen = max(map(len, lines))
    rowSep = '\n' + rowSep*maxLen + '\n'
    return rowSep.join(lines)

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'),
                      )





More information about the Python-list mailing list