Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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)
share|improve this question
1  
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

1 Answer 1

A slightly more readable version:

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 ;).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.