Solution
You can use the following custom code to display tables without using any other package. However, why reinvent the wheel? If you can, you should either use one of the following:
tabulate
pandas.Dataframe.to_markdown
pandas.Dataframe.to_string
To use the code given below, run this:
_ = maketable(data=lst, headers=headers, headersep='-', showtable=True)
## Output:
| Name | Age | Gender |
|-------|-----|--------|
| Milan | 14 | Male |
| Alex | 482 | Male |
| John | 12 | Male |
| Jake | 36 | Male |
| James | 12 | Male |
Extended Example of Code Usage
lst = [
["Milan", 14, "Male"],
["Alex", 482, "Male"],
["John", 12, "Male"],
["Jake", 36, "Male"],
["James", 12, "Male"]
]
headers = ['Name', 'Age', 'Gender']
tabeltext = maketable(
data = lst, # the data to create the table
headers = headers, # list of headers
bufferlen = 1, # length of buffers spaces to use around each table-cell-value
headersep = '-', # seperator-line-character to use between hear row and the rest of the table
data_has_header = False, # if `data` parameter has headers or not
showtable = True # whether to print the table or not
)
Code
from typing import List
def get_column_widths(
data: List[List],
headers: List[str] = None,
num_cols: int = None) -> List[int]:
"""returns column widths from the table data.
Example:
lst = [
["Milan", 14, "Male"],
["Alex", 482, "Male"],
["John", 12, "Male"],
["Jake", 36, "Male"],
["James", 12, "Male"]
]
headers = ['Name', 'Age', 'Gender']
get_column_widths(data=lst, headers=headers, num_cols=None)
"""
if (num_cols is None) and (headers is None):
num_cols = len(data[0])
if headers:
num_cols = len(headers)
_data = [headers] + data
else:
_data = data.copy()
col_widths = [0 for _ in range(num_cols)]
for ridx, line in enumerate(_data):
for cidx, e in enumerate(line):
col_width = len(str(e))
if col_width > col_widths[cidx]:
col_widths[cidx] = col_width
return col_widths
def pad(text: str, length: int) -> str:
return text + ' '*length
def wraptext(text: str, length: int) -> str:
return text[:length] + '\n' + text[length:]
def pad_or_wrap(text: str, length: int = 10) -> str:
n = len(text)
if n > length:
text = wraptext(text=text, length=length)
elif n < length:
text = pad(text=text, length=length-n)
return text
def maketable(
data: List[List],
headers: List[str] = None,
bufferlen: int = 1,
headersep: str = '-',
data_has_header: bool = False,
showtable: bool=True) -> str:
"""Returns the table as a string.
Example:
lst = [
["Milan", 14, "Male"],
["Alex", 482, "Male"],
["John", 12, "Male"],
["Jake", 36, "Male"],
["James", 12, "Male"]
]
headers = ['Name', 'Age', 'Gender']
tabeltext = maketable(
data = lst, # the data to create the table
headers = headers, # list of headers
bufferlen = 1, # length of buffers spaces to use around each table-cell-value
headersep = '-', # seperator-line-character to use between hear row and the rest of the table
data_has_header = False, # if `data` parameter has headers or not
showtable = True # whether to print the table or not
)
"""
tablerows = []
bufferlen = 1
buffertext = '' if bufferlen == 0 else ' ' * bufferlen
if headers:
num_cols = len(headers)
if not data_has_header:
_data = [headers] + data
else:
if data_has_header:
headers = data[0]
num_cols = len(headers)
_data = data.copy()
col_widths = get_column_widths(data = _data)
for ridx, line in enumerate(_data):
tablerows.append(
'|' + '|'.join(
buffertext + \
pad_or_wrap(text = str(e),
length = col_widths[cidx]) + \
buffertext \
for cidx, e in enumerate(line)
) + '|'
)
if headers or data_has_header:
if ridx == 0:
tablerows.append(
'|' + '|'.join(
[headersep * (col_widths[cidx] + 2 * bufferlen) \
for cidx in range(num_cols)]
) + '|'
)
tabletext = '\n'.join(tablerows)
if showtable:
print(tabletext)
return tabletext