# Nicely tabulate a list of strings for printing

I have a list of strings of variable lengths, and I want to pretty-print them so they are lining up in columns. I have the following code, which works as I want it to currently, but I feel it is a bit ugly. How can I simplify it/make it more pythonic (without changing the output behaviour)?

For starters I think I could probably use the alignment '<' option of the str.format stuff if I could just figure out the syntax properly...

def tabulate(words, termwidth=79, pad=3):
width = len(max(words, key=len))
ncols = max(1, termwidth // (width + pad))
nrows = len(words) // ncols + (1 if len(words) % ncols else 0)
#import itertools
#table = list(itertools.izip_longest(*[iter(words)]*ncols, fillvalue=''))  # row-major
table = [words[i::nrows] for i in xrange(nrows)]                          # column-major
return '\n'.join(''.join((' '*pad + x.ljust(width) for x in r)) for r in table)

-
Not worth an answer, but you can get your rounded-up-not-down integer division to compute nrows in a much more compact form as nrows = (len(words) - 1) // ncols + 1. Seee e.g. en.wikipedia.org/wiki/Floor_and_ceiling_functions#Quotients –  Jaime Feb 1 '13 at 7:20
Thanks, I knew there was a better way when I was writing that... I'd just forgotten the usual trick (which, actually, I usually used adding the denominator - 1 to the numerator, i.e. (len(words) + ncols - 1) // ncols ... it seems to be equivalent to your trick –  wim Feb 1 '13 at 12:26
I found a nice alternative, after pip install prettytable. No need to reinvent the wheel I guess .. –  wim Feb 21 '13 at 2:26

def tabulate(words, termwidth=79, pad=3):
width = len(max(words, key=len)) + pad
ncols = max(1, termwidth // width)
nrows = (len(words) - 1) // ncols + 1
table = []
for i in xrange(nrows):
row = words[i::nrows]
format_str = ('%%-%ds' % width) * len(row)
table.append(format_str % tuple(row))
return '\n'.join(table)


Most notably, I've defined width to include padding and using string formatting to generate a format string to format each row ;).

-