As a part of a console utilities module, I created a function that takes a table in the form of an array of arrays, and generates an ASCII table with the given contents.
I've also added the options of adding a header, determining the in-cell alignment, and adding a border to the table.
Table cells have auto computed lengths by the longest cell of their column, rows that have a small amount of elements get filled by blank cells to adjust their length.
I'm quite new to Python, so I wanted to know about whether my writing style is OK. Can I improve or shorten some parts of the code? Any other advice?
def ascii_table (table, **k):
header = k.get('header', [])
align = k.get('align', 'left')
border = k.get('border', False)
widths = []
for i in range(max(map(len, table))): widths.append(max(max(map(len, [row[i] for row in table if len(row) > i])), len(header[i]) if len(header) > i else 0))
printable = []
if border:
printrow = []
for i in range(max(map(len, table))):
if i > 0 and i < max(map(len, table)) - 1: printrow.append('─' * (widths[i] + 2))
else: printrow.append('─' * (widths[i] + 1))
printable.append('┌─' + '┬'.join(printrow) + '─┐')
# header formatting
if len(header) > 0:
printrow = []
for i in range(len(header)):
assert header[i]
if align == 'center': printrow.append(header[i].center(widths[i]))
elif align == 'left': printrow.append(header[i].ljust(widths[i]))
elif align == 'right': printrow.append(header[i].rjust(widths[i]))
if border: printable.append('│ ' + ' │ '.join(printrow) + ' │')
else: printable.append(' │ '.join(printrow))
printrow = []
for i in range(len(header)):
if i > 0 and i < len(header) - 1: printrow.append('─' * (widths[i] + 2))
else: printrow.append('─' * (widths[i] + 1))
if border: printable.append('├─' + '┼'.join(printrow) + '─┤')
else: printable.append('┼'.join(printrow))
# table formatting
for row in table:
printrow = []
for i in range(len(widths) - len(row)):
row.append('')
for i in range(len(row)):
if align == 'center': printrow.append(row[i].center(widths[i]))
elif align == 'left': printrow.append(row[i].ljust(widths[i]))
elif align == 'right': printrow.append(row[i].rjust(widths[i]))
if border: printable.append('│ ' + ' │ '.join(printrow) + ' │')
else: printable.append(' │ '.join(printrow))
if border:
printrow = []
for i in range(max(map(len, table))):
if i > 0 and i < max(map(len, table)) - 1: printrow.append('─' * (widths[i] + 2))
else: printrow.append('─' * (widths[i] + 1))
printable.append('└─' + '┴'.join(printrow) + '─┘')
return '\n'.join(printable)
Demo:
>>> from asciiart import ascii_table >>> table = list(map(lambda x: x.split(), ['Jon Doe 20', 'Mark Waine 35', 'Donald Rory 43'])) >>> header = ['First Name', 'Last Name', 'Age'] >>> ascii = ascii_table(table, header=header, align='center', border=True) >>> print(ascii) ┌────────────┬───────────┬─────┐ │ First Name │ Last Name │ Age │ ├────────────┼───────────┼─────┤ │ Jon │ Doe │ 20 │ │ Mark │ Waine │ 35 │ │ Donald │ Rory │ 43 │ └────────────┴───────────┴─────┘
**k
as a formal parameter instead of the more explicitdef ascii_table(table, header=None, align='left', border=False)
? Nice question in any case! \$\endgroup\$