Skip to content

Instantly share code, notes, and snippets.

@bpeterso2000
Last active February 18, 2023 02:25
Show Gist options
  • Save bpeterso2000/976777a4a4a1d09af32d6b80910da59d to your computer and use it in GitHub Desktop.
Save bpeterso2000/976777a4a4a1d09af32d6b80910da59d to your computer and use it in GitHub Desktop.
Display a list of lists as a simple text table with rows, columns and an optional header.
from math import log10
from typing import Sequence
def print_table(rows: Sequence[Sequence], hdr=True, rownums=True) -> None:
"""Display as a simple text table; rows, columns & optional header.
rows:
Rows & columns where each cell object is a string or can be
converted into a string.
hdr:
Indicates that the first row contains header labels
rownums:
Adda a new column at the beginning of the table containing
row numbers.
raises:
TypeError if a cell can't be coverted to a string.
tailored for low-complexity:
* If rows differ in numbers of columns then blank cells will
be padded to ensure every row has the same number of columns.
* The text in the cells will be always be left aligned;
doesn't support other alignments.
* The borders are always drawn with pluses (+) and dashes (-);
doesn't support border customization
* Doesn't support word wrapping in cells.
* Doesn't check and limit column sizes to fit terminal width.
* Doesn't support column or row spanning.
>>> table = [
... ['Element', 'Symbol', 'Upper Crustal Abundance (ppm)'],
... ['Cerium', 'Ce', 64],
... ['Lanthanum', 'La', 30]
... ]
>>> print_table(table)
+---+-----------+--------+-------------------------------+
| | Element | Symbol | Upper Crustal Abundance (ppm) |
+---+-----------+--------+-------------------------------+
| 1 | Cerium | Ce | 64 |
| 2 | Lanthanum | La | 30 |
+---+-----------+--------+-------------------------------+
>>> print_table(table, rownums=False)
+-----------+--------+-------------------------------+
| Element | Symbol | Upper Crustal Abundance (ppm) |
+-----------+--------+-------------------------------+
| Cerium | Ce | 64 |
| Lanthanum | La | 30 |
+-----------+--------+-------------------------------+
>>> table = table[1:]
>>> print_table(table, hdr=False)
+---+-----------+----+----+
| 1 | Cerium | Ce | 64 |
| 2 | Lanthanum | La | 30 |
+---+-----------+----+----+
>>> print_table(table, hdr=False, rownums=False)
+-----------+----+----+
| Cerium | Ce | 64 |
| Lanthanum | La | 30 |
+-----------+----+----+
>>> table = [['Element', 'Symbol', 'No Data'], ['Cerium', 'Ce']]
>>> print_table(table)
+---+---------+--------+---------+
| | Element | Symbol | No Data |
+---+---------+--------+---------+
| 1 | Cerium | Ce | |
+---+---------+--------+---------+
"""
# ensure each row has the same number of columns
uniq_num_cols = {len(i) for i in rows}
if len(uniq_num_cols) > 1:
num_cols = max(uniq_num_cols)
rows = [i + [''] * (num_cols - len(i)) for i in rows]
# add a column containing the row numbers
if rownums:
rows = rows[:]
if hdr:
rows[0] = [''] + rows[0]
for num in range(hdr, len(rows)):
rows[num] = [num + (not hdr)] + rows[num]
try:
widths = [max(len(str(j)) for j in i) for i in zip(*rows)]
except TypeError:
raise
# draw table
res = []
for row in rows:
cols = ' | '.join(str(j).ljust(k) for j, k in zip(row, widths))
res.append(f'| {cols} |')
hsep = ['+%s+' % '+'.join('-' * (i + 2) for i in widths)]
if hdr:
res = res[:1] + hsep + res[1:]
print('\n'.join(hsep + res + hsep))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment