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
Found this question as a met almost the same task. And I've created function to print list in multi columns with the number of columns as parameter. Maybe not so elegant as one-liner solutions, but it could be useful for someone.
However, it handles incomplete lists, ex.: it can print list of 11 in 3 rows.
Function splitted for better readability:
def is_printable(my_list):
return len(my_list) > 0
def create_empty_list(columns):
result = []
for num in range(0, columns):
result.append([])
return result
def fill_empty_list(empty_list, my_list, columns):
column_depth = len(my_list) / columns if len(my_list) % columns == 0 else len(my_list) / columns + 1
item_index = 0
for column in range(0, columns):
while len(empty_list[column]) < column_depth:
if item_index < len(my_list):
empty_list[column].append(my_list[item_index])
else:
empty_list[column].append(" ") # last column could be incomplete, fill it with space
item_index += 1
def print_list_in_columns(my_list, columns=1):
if not is_printable(my_list):
print 'Nothing to print, sorry...'
return
column_width = 25 #(in symbols) Also can be calculated automatically
list_to_print = create_empty_list(columns)
fill_empty_list(list_to_print, my_list, columns)
iterators = ["it" + str(i) for i in range(0, columns)]
for iterators in zip(*list_to_print):
print ("".join(str.ljust(i, column_width) for i in iterators))
and the call part:
foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf',
'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel',
'qgis1.1', 'php_mapscript']
print_list_in_columns(foolist, 2)
Although not designed for it, the standard-library module cmd has a utility for printing a list of strings in multiple columns
import cmd
cli = cmd.Cmd()
cli.columnize(foolist, displaywidth=80)
You even then have the option of specifying the output location, with cmd.Cmd(stdout=my_stream)
See formatting-a-list-of-text-into-columns,
A general solution, handles any number of columns and odd lists. Tab characters separate columns, using generator expressions to save space.
def fmtcols(mylist, cols):
lines = ("\t".join(mylist[i:i+cols]) for i in xrange(0,len(mylist),cols))
return '\n'.join(lines)
It's useful to allow for uneven columns, without having to know in advance how many columns you can fit:
>>> words = [string.ascii_lowercase] + list(string.ascii_lowercase)
>>> print format_list(words)
abcdefghijklmnopqrstuvwxyz b d f h j l n p r t v x z
a c e g i k m o q s u w y
For your example:
>>> foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi',
... 'netcdf', 'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv',
... 'qgis-devel', 'qgis1.1', 'php_mapscript']
>>> print format_list(foolist, spacing=4, width=31)
exiv2-devel msvcrt
mingw-libs gdal-grass
tcltk-demos iconv
fcgi qgis-devel
netcdf qgis1.1
pdcurses-devel php_mapscript
Here is the code. Note that it also handles words with ANSI color codes (such as from the colorama package) - they won't mess up the column widths.
ansi_pattern = re.compile(r'\x1b\[\d{1,2}m')
def get_nchars(string):
"""Return number of characters, omitting ANSI codes."""
return len(ansi_pattern.sub('', string))
def format_list(items, indent=0, spacing=2, width=79):
"""Return string listing items along columns.
items : sequence
List of items to display that must be directly convertible into
unicode strings. ANSI color codes may be present, and are taken
into account in determining column widths
indent : int
Number of spaces in left margin.
spacing : int
Number of spaces between columns.
width : int
Maximum number of characters per line, including indentation.
"""
if not items:
return u''
# Ensure all items are strings
items = [unicode(item) for item in items]
# Estimate number of columns based on shortest and longest items
minlen = min(get_nchars(item) for item in items)
maxlen = max(get_nchars(item) for item in items)
# Assume one column with longest width, remaining with shortest.
# Use negative numbers for ceiling division.
ncols = 1 - (-(width - indent - maxlen) // (spacing + min(1, minlen)))
ncols = max(1, min(len(items), ncols))
# Reduce number of columns until items fit (or only one column)
while ncols >= 1:
# Determine number of rows by ceiling division
nrows = -(-len(items) // ncols)
# Readjust to avoid empty last column
ncols = -(-len(items) // nrows)
# Split items into columns, and test width
columns = [items[i*nrows:(i+1)*nrows] for i in range(ncols)]
totalwidth = indent - spacing + sum(
spacing + max(get_nchars(item) for item in column)
for column in columns
)
# Stop if columns fit. Otherwise, reduce number of columns and
# try again.
if totalwidth <= width:
break
else:
ncols -= 1
# Pad all items to column width
for i, column in enumerate(columns):
colwidth = max(get_nchars(item) for item in column)
columns[i] = [
item + ' ' * (colwidth - get_nchars(item))
for item in column
]
# Transpose into rows, and return joined rows
rows = list(itertools.izip_longest(*columns, fillvalue=''))
return '\n'.join(
' ' * indent + (u' ' * spacing).join(row).rstrip()
for row in rows
)
I needed to adjust each of the columns. I have implemented this code
def print_sorted_list(data, columns):
if data:
gap = 2
ljusts = {}
for count, item in enumerate(sorted(data), 1):
column = count % columns
ljusts[column] = len(item) if (column not in ljusts) else max(ljusts[column], len(item))
for count, item in enumerate(sorted(data), 1):
print item.ljust(ljusts[count % columns] + gap),
if (count % columns == 0) or (count == len(data)):
print
Example:
foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf',
'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel',
'qgis1.1', 'php_mapscript', 'blablablablablablabla', 'fafafafafafa']
print_sorted_list(foolist, 4)
Output:
blablablablablablabla exiv2-devel fafafafafafa fcgi
gdal-grass iconv mingw-libs msvcrt
netcdf pdcurses-devel php_mapscript qgis-devel
qgis1.1 tcltk-demos
For Python >=3.6, slight update to @JoshuaZastrow's answer using f-strings and adding clear method to adjust columns
cols = 5
[print(f'{key:20}', end='\t') if (idx + 1) % cols else print(f'{key}') for idx, key in enumerate(list_variable)]
or
cols = 5
for idx, key in enumerate(list_variable):
if (idx + 1) % cols:
print(f'{key:20}', end='\t')
else:
print(f'{key}')