Python function for displaying a list of dictionaries in table format
December 3, 2010
I just spent like 2 hours writing this function, but it was worth it!
This cut down a lot of duplicate code on the project I'm working on. I figured I'd post it here in case someone is trying to do the same thing. I'm sure my code is not optimal so if you have any suggestions on how to improve it please feel free to comment :).
from operator import itemgetter
def format_as_table(data,
keys,
header=None,
sort_by_key=None,
sort_order_reverse=False):
"""Takes a list of dictionaries, formats the data, and returns
the formatted data as a text table.
Required Parameters:
data - Data to process (list of dictionaries). (Type: List)
keys - List of keys in the dictionary. (Type: List)
Optional Parameters:
header - The table header. (Type: List)
sort_by_key - The key to sort by. (Type: String)
sort_order_reverse - Default sort order is ascending, if
True sort order will change to descending. (Type: Boolean)
"""
# Sort the data if a sort key is specified (default sort order
# is ascending)
if sort_by_key:
data = sorted(data,
key=itemgetter(sort_by_key),
reverse=sort_order_reverse)
# If header is not empty, add header to data
if header:
# Get the length of each header and create a divider based
# on that length
header_divider = []
for name in header:
header_divider.append('-' * len(name))
# Create a list of dictionary from the keys and the header and
# insert it at the beginning of the list. Do the same for the
# divider and insert below the header.
header_divider = dict(zip(keys, header_divider))
data.insert(0, header_divider)
header = dict(zip(keys, header))
data.insert(0, header)
column_widths = []
for key in keys:
column_widths.append(max(len(str(column[key])) for column in data))
# Create a tuple pair of key and the associated column width for it
key_width_pair = zip(keys, column_widths)
format = ('%-*s ' * len(keys)).strip() + '\n'
formatted_data = ''
for element in data:
data_to_format = []
# Create a tuple that will be used for the formatting in
# width, value format
for pair in key_width_pair:
data_to_format.append(pair[1])
data_to_format.append(element[pair[0]])
formatted_data += format % tuple(data_to_format)
return formatted_data
# Test
if __name__ == '__main__':
header = ['Name', 'Age', 'Sex']
keys = ['name', 'age', 'sex']
sort_by_key = 'age'
sort_order_reverse = True
data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
{'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
{'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]
print format_as_table(data,
keys,
header,
sort_by_key,
sort_order_reverse)Output:
Name Age Sex ---- --- --- Bill Clinton 57 M John Doe 37 M Lisa Simpson 17 F