3

I'm working on a command line interpreter, and I have a function which prints out a long list of strings in a easy to read manner.

The function is:

def pretty_print(CL_output):
    if len(CL_output)%2 == 0:
        #even
        print "\n".join("%-20s %s"%(CL_output[i],CL_output[i+len(CL_output)/2]) for i in range(len(CL_output)/2))    
    else:
        #odd
        d_odd = CL_output + ['']
        print "\n".join("%-20s %s"%(d_odd[i],d_odd[i+len(d_odd)/2]) for i in range(len(d_odd)/2))

So, for a list such as:

myList = ['one','potato','two','potato','three','potato','four','potato'...]

The function pretty_print returns:

pretty_print(myList)

>>> one                  three
    potato               potato
    two                  four
    potato               potato

However for a larger list, the function pretty_print still prints out the list in two columns. Is there a way to modify pretty_print so that it prints out a list on 3 or 4 columns depending on the size of the list? So len(myList) ~ 100, pretty_print will print out on 3 lines and for len(myList) ~ 300, pretty_print will print out on 4 columns.

So if i have:

  myList_long = ['one','potato','two','potato','three','potato','four','potato'...
           'one hundred`, potato ...... `three hundred`,potato]

The desired output is:

pretty_print(myList_long)

>>> one                  three                one hundred          three hundred
    potato               potato               potato               potato
    two                  four                 ...                  ...
    potato               potato               ...                  ....
Holtz
  • 213
  • 1
  • 5
  • 12
  • 1
    You could calculate the number of columns as `num_columns = len(list) // 100 + 2`. That would give you 3 columns for 100, and 5 columns for 300 (while still being a linear function). – sdasdadas Nov 08 '13 at 16:05
  • Looks like you want something like [this answer].(http://stackoverflow.com/a/1524333/443348). – Ramchandra Apte Nov 08 '13 at 16:16
  • Perhaps this is a non-issue for your project, but how do you want to handle items in the list that are very **wide**: `really-hairy-moldy-rotten-potato-with-cheese`. – FMc Nov 08 '13 at 16:21
  • @FMc, interesting question. This wouldn't occur in my project, but my caveat is that the print out on the CL is neat and easy to read, so perhaps putting the `really-hairy-moldy-rotten-potato-with-cheese` in it's own column on the end could work. Or putting in a separator between each string so you can distinguish between them easily. – Holtz Nov 08 '13 at 18:50

2 Answers2

2

Modified from this answer.

def pretty_print(CL_output):
    columns = len(CL_output)//200+2
    lines = ("".join(s.ljust(20) for s in CL_output[i:i+columns-1])+CL_output[i:i+columns][-1] for i in range(0, len(CL_output), columns))
    return "\n".join(lines)
Community
  • 1
  • 1
Ramchandra Apte
  • 3,835
  • 2
  • 22
  • 39
0

I have a solution which also takes terminal width as input and displays only as many columns that can be fit in it. See: https://gist.github.com/critiqjo/2ca84db26daaeb1715e1

col_print.py

def col_print(lines, term_width=80, indent=0, pad=2):
  n_lines = len(lines)
  if n_lines == 0:
    return

  col_width = max(len(line) for line in lines)
  n_cols = int((term_width + pad - indent)/(col_width + pad))
  n_cols = min(n_lines, max(1, n_cols))

  col_len = int(n_lines/n_cols) + (0 if n_lines % n_cols == 0 else 1)
  if (n_cols - 1) * col_len >= n_lines:
    n_cols -= 1

  cols = [lines[i*col_len : i*col_len + col_len] for i in range(n_cols)]

  rows = list(zip(*cols))
  rows_missed = zip(*[col[len(rows):] for col in cols[:-1]])
  rows.extend(rows_missed)

  for row in rows:
    print(" "*indent + (" "*pad).join(line.ljust(col_width) for line in row))
bummi
  • 26,435
  • 13
  • 58
  • 97
John
  • 1,477
  • 1
  • 18
  • 29