This is similar to How to print a list in Python “nicely”, but I would like to print the list even more nicely -- without the brackets and apostrophes and commas, and even b
Simple:
l = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf',
'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel',
'qgis1.1', 'php_mapscript']
if len(l) % 2 != 0:
l.append(" ")
split = len(l)/2
l1 = l[0:split]
l2 = l[split:]
for key, value in zip(l1,l2):
print '%-20s %s' % (key, value) #python <2.6
print "{0:<20s} {1}".format(key, value) #python 2.6+
There are tons of answers already, but I will share my solution, which in addition to printing the list into multiple columns, it also chooses the amount of columns dynamically, from the terminal width and the longest string on the list.
import os
cols = os.popen('stty size', 'r').read().split()[1]
def print_multicol(my_list):
max_len = len(max(my_list,key=len)) + 2
ncols = (int(cols) -4 ) / max_len
while my_list:
n = 0
while n < ncols:
if len(my_list) > 0 :
fstring = "{:<"+str(max_len)+"}"
print fstring.format(my_list.pop(0)),
n += 1
print
a_list = "a ab abc abcd abcde b bc bcde bcdef c cde cdef cdfg d de defg"
a_list += "defgh e ef efg efghi efghij f fg fgh fghij fghijk"
print_multicol(a_list.split())
Here is a straightforward way. See the inline comments for explanation:
import shutil
import itertools
from functools import reduce
def split_list(lst, ncols):
"""Split list into rows"""
return itertools.zip_longest(
*[lst[i::ncols] for i in range(ncols)], fillvalue=""
)
# -- Alternatively --
# import numpy as np
# array = np.array(lst)
# nrows = array.size / ncols + 1
# return np.array_split(array, int(nrows))
def print_in_columns(lst):
"""Print a list in columns."""
# Find maximum length of a string in colors_list
colsize = reduce(lambda x, y: max(x, len(y)), lst, 0)
# Terminal width
maxcols = shutil.get_terminal_size()[0]
ncols = maxcols / (colsize + 1)
rows = split_list(lst, int(ncols))
print(
# Join rows
"\n".join(
(
# Fill items left justified
" ".join(item.ljust(colsize) for item in row)
for row in rows
)
)
)
This answer uses the same method in the answer by @Aaron Digulla, with slightly more pythonic syntax. It might make some of the above answers easier to understand.
>>> for a,b,c in zip(foolist[::3],foolist[1::3],foolist[2::3]):
>>> print '{:<30}{:<30}{:<}'.format(a,b,c)
exiv2-devel mingw-libs tcltk-demos
fcgi netcdf pdcurses-devel
msvcrt gdal-grass iconv
qgis-devel qgis1.1 php_mapscript
This can be easily adapt to any number of columns or variable columns, which would lead to something like the answer by @gnibbler. The spacing can be adjusted for screen width.
Update: Explanation as requested.
Indexing
foolist[::3] selects every third element of foolist. foolist[1::3] selects every third element, starting at the second element ('1' because python uses zero-indexing).
In [2]: bar = [1,2,3,4,5,6,7,8,9]
In [3]: bar[::3]
Out[3]: [1, 4, 7]
zip
Zipping lists (or other iterables) generates tuples of the elements of the the lists. For example:
In [5]: zip([1,2,3],['a','b','c'],['x','y','z'])
Out[5]: [(1, 'a', 'x'), (2, 'b', 'y'), (3, 'c', 'z')]
together
Putting these ideas together we get our solution:
for a,b,c in zip(foolist[::3],foolist[1::3],foolist[2::3]):
Here we first generate three "slices" of foolist, each indexed by every-third-element and offset by one. Individually they each contain only a third of the list. Now when we zip these slices and iterate, each iteration gives us three elements of foolist.
Which is what we wanted:
In [11]: for a,b,c in zip(foolist[::3],foolist[1::3],foolist[2::3]):
....: print a,b,c
Out[11]: exiv2-devel mingw-libs tcltk-demos
fcgi netcdf pdcurses-devel
[etc]
Instead of:
In [12]: for a in foolist:
....: print a
Out[12]: exiv2-devel
mingw-libs
[etc]
Here's a solution in python 3.4 that automatically detects terminal width and takes it into account. Tested on Linux and Mac.
def column_print(list_to_print, column_width=40):
import os
term_height, term_width = os.popen('stty size', 'r').read().split()
total_columns = int(term_width) // column_width
total_rows = len(list_to_print) // total_columns
# ceil
total_rows = total_rows + 1 if len(list_to_print) % total_columns != 0 else total_rows
format_string = "".join(["{%d:<%ds}" % (c, column_width) \
for c in range(total_columns)])
for row in range(total_rows):
column_items = []
for column in range(total_columns):
# top-down order
list_index = row + column*total_rows
# left-right order
#list_index = row*total_columns + column
if list_index < len(list_to_print):
column_items.append(list_to_print[list_index])
else:
column_items.append("")
print(format_string.format(*column_items))
The way Aaron has done it can work with more than two colums
>>> l = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf',
... 'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel',
... 'qgis1.1', 'php_mapscript']
>>> cols = 4
>>> split=[l[i:i+len(l)/cols] for i in range(0,len(l),len(l)/cols)]
>>> for row in zip(*split):
... print "".join(str.ljust(i,20) for i in row)
...
exiv2-devel fcgi msvcrt qgis-devel
mingw-libs netcdf gdal-grass qgis1.1
tcltk-demos pdcurses-devel iconv php_mapscript