Created
June 10, 2017 04:55
-
-
Save sadikovi/8a2b9a472729f17f387cb53ffbdcbee6 to your computer and use it in GitHub Desktop.
Display table nicely in Python with margin and projection (table is a list of dictionary rows)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################ | |
# Example | |
################################################################ | |
print("\n# Empty rows list") | |
show([]) | |
print("\n# Rows list with inconsistent set of columns and margin of 4 spaces") | |
rows = [ | |
{"col1": 1, "col2": 2.1, "col3": "long text", "col4": "", "col5": True}, | |
{"col1": 2, "col2": 3.2, "col3": "def"}, | |
{"col1": 3, "col2": 4.3334, "col3": "ghi", "col4": None} | |
] | |
show(rows, margin=4) | |
print("\n# Rows with different value types and enforced column order") | |
rows = [ | |
{"sdate": "2015-01-01", "min": 1.0234, "max": 3935.234, "mean": 1.2, "std": "NaN"}, | |
{"sdate": "2015-01-02", "min": 1.234, "max": 234.2, "mean": 34.2, "std": "NaN"}, | |
{"sdate": "2015-01-03", "min": 1.0, "max": 3.8, "mean": 2.3, "std": "NaN"}, | |
{"sdate": "2015-01-04", "min": 2.04, "max": 810.34, "mean": 789.32, "std": "NaN"}, | |
{"sdate": "2015-01-05", "min": "NaN", "max": "NaN", "mean": 0.001, "std": "NaN"} | |
] | |
show(rows, columns=["sdate", "min", "max", "mean", "std"]) | |
show(rows, margin=4, columns=["sdate", "mean"]) | |
""" | |
# Empty rows list | |
++ | |
|| | |
++ | |
++ | |
# Rows list with inconsistent set of columns and margin of 4 spaces | |
+-----+-----+-------+----------+-----+ | |
| col4| col5| col2| col3| col1| | |
+-----+-----+-------+----------+-----+ | |
| | True| 2.1| long text| 1| | |
| | | 3.2| def| 2| | |
| None| | 4.3334| ghi| 3| | |
+-----+-----+-------+----------+-----+ | |
# Rows with different value types and enforced column order | |
+-----------+-------+---------+-------+----+ | |
| sdate| min| max| mean| std| | |
+-----------+-------+---------+-------+----+ | |
| 2015-01-01| 1.0234| 3935.234| 1.2| NaN| | |
| 2015-01-02| 1.234| 234.2| 34.2| NaN| | |
| 2015-01-03| 1.0| 3.8| 2.3| NaN| | |
| 2015-01-04| 2.04| 810.34| 789.32| NaN| | |
| 2015-01-05| NaN| NaN| 0.001| NaN| | |
+-----------+-------+---------+-------+----+ | |
+-----------+-------+ | |
| sdate| mean| | |
+-----------+-------+ | |
| 2015-01-01| 1.2| | |
| 2015-01-02| 34.2| | |
| 2015-01-03| 2.3| | |
| 2015-01-04| 789.32| | |
| 2015-01-05| 0.001| | |
+-----------+-------+ | |
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
def table(rows, margin=0, columns=[]): | |
""" | |
Return string representing table content, returns table as string and as a list of strings. | |
It is okay for rows to have different sets of keys, table will show union of columns with | |
missing values being empty spaces. | |
:param rows: list of dictionaries as rows | |
:param margin: left space padding to apply to each row, default is 0 | |
:param columns: extract listed columns in provided order, other columns will be ignored | |
:return: table content as string and as list | |
""" | |
def projection(cols, columns): | |
return [(x, cols[x]) for x in columns if x in cols] if columns else cols.items() | |
def row_to_string(row, columns): | |
values = [(row[name] if name in row else "").rjust(size) for name, size in columns] | |
return "|%s|" % ("|".join(values)) | |
def header(columns): | |
return "|%s|" % ("|".join([name.rjust(size) for name, size in columns])) | |
def divisor(columns): | |
return "+%s+" % ("+".join(["-" * size for name, size in columns])) | |
data = [dict([(str(a), str(b)) for a, b in row.items()]) for row in rows] | |
cols = dict([(x, len(x) + 1) for row in data for x in row.keys()]) if data else {} | |
for row in data: | |
for key in row.keys(): | |
cols[key] = max(cols[key], len(row[key]) + 1) | |
proj = projection(cols, columns) # extract certain columns to display (or all if not provided) | |
table = [divisor(proj), header(proj), divisor(proj)] + \ | |
[row_to_string(row, proj) for row in data] + [divisor(proj)] | |
table = ["%s%s" % (" " * margin, tpl) for tpl in table] if margin > 0 else table | |
table_text = "\n".join(table) | |
return (table_text, table) | |
def show(rows, margin=0, columns=[]): | |
""" | |
Print table in console for list of rows. | |
""" | |
txt, _ = table(rows, margin, columns) | |
print(txt) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment