I have a list of dicts with the fields classid, dept, coursenum, area, and title from a sql query. I would like to output the values in a human readable format. I was thinking a Column header at the top of each and then in each column the approrpiate output ie:
我有一个dicts列表,其中包含来自sql查询的字段classid,dept,coursenum,area和title。我想以人类可读的格式输出值。我在每个顶部想到一个Column标题,然后在每一列中考虑approrpiate输出,即:
CLASSID DEPT COURSE NUMBER AREA TITLE
foo bar foo bar foo
yoo hat yoo bar hat
(obviously with standard alignment/spacing)
(显然标准对齐/间距)
How would I accomplish this in python?
我如何在python中实现这一目标?
5 个解决方案
#1
55
Standard Python string formatting may suffice.
标准Python字符串格式化可能就足够了。
# assume that your data rows are tuples
template = "{0:8}|{1:10}|{2:15}|{3:7}|{4:10}" # column widths: 8, 10, 15, 7, 10
print template.format("CLASSID", "DEPT", "COURSE NUMBER", "AREA", "TITLE") # header
for rec in your_data_source:
print template.format(*rec)
Or
# assume that your data rows are dicts
template = "{CLASSID:8}|{DEPT:10}|{C_NUM:15}|{AREA:7}|{TITLE:10}" # same, but named
print template.format( # header
CLASSID="CLASSID", DEPT="DEPT", C_NUM="COURSE NUMBER",
AREA="AREA", TITLE="TITLE"
)
for rec in your_data_source:
print template.format(**rec)
Play with alignment, padding, and exact format specifiers to get best results.
使用对齐,填充和精确格式说明符来获得最佳结果。
#2
11
class TablePrinter(object):
"Print a list of dicts as a table"
def __init__(self, fmt, sep=' ', ul=None):
"""
@param fmt: list of tuple(heading, key, width)
heading: str, column label
key: dictionary key to value to print
width: int, column width in chars
@param sep: string, separation between columns
@param ul: string, character to underline column label, or None for no underlining
"""
super(TablePrinter,self).__init__()
self.fmt = str(sep).join('{lb}{0}:{1}{rb}'.format(key, width, lb='{', rb='}') for heading,key,width in fmt)
self.head = {key:heading for heading,key,width in fmt}
self.ul = {key:str(ul)*width for heading,key,width in fmt} if ul else None
self.width = {key:width for heading,key,width in fmt}
def row(self, data):
return self.fmt.format(**{ k:str(data.get(k,''))[:w] for k,w in self.width.iteritems() })
def __call__(self, dataList):
_r = self.row
res = [_r(data) for data in dataList]
res.insert(0, _r(self.head))
if self.ul:
res.insert(1, _r(self.ul))
return '\n'.join(res)
and in use:
并在使用中:
data = [
{'classid':'foo', 'dept':'bar', 'coursenum':'foo', 'area':'bar', 'title':'foo'},
{'classid':'yoo', 'dept':'hat', 'coursenum':'yoo', 'area':'bar', 'title':'hat'},
{'classid':'yoo'*9, 'dept':'hat'*9, 'coursenum':'yoo'*9, 'area':'bar'*9, 'title':'hathat'*9}
]
fmt = [
('ClassID', 'classid', 11),
('Dept', 'dept', 8),
('Course Number', 'coursenum', 20),
('Area', 'area', 8),
('Title', 'title', 30)
]
print( TablePrinter(fmt, ul='=')(data) )
produces
ClassID Dept Course Number Area Title
=========== ======== ==================== ======== ==============================
foo bar foo bar foo
yoo hat yoo bar hat
yooyooyooyo hathatha yooyooyooyooyooyooyo barbarba hathathathathathathathathathat
#3
4
This function takes list comprehension to a bit of an extreme, but it accomplishes what you're looking for with optimal performance:
这个函数使列表理解有点极端,但它以最佳性能完成了你正在寻找的东西:
algorithm:
- find longest field in each column; i.e., 'max(map(len, column_vector))'
- for each field (left to right, top to bottom), call str.ljust to align it to the left boundary of the column it belongs to.
- join fields with desired amount of separating whitespace (creating a row).
- join collection of rows with a newline.
在每列中找到最长的字段;即'max(map(len,column_vector))'
对于每个字段(从左到右,从上到下),调用str.ljust将其对齐到它所属列的左边界。
连接具有所需分隔空白量的字段(创建一行)。
使用换行符连接行集合。
row_collection: list of iterables (dicts/sets/lists), each containing data for one row.
row_collection:iterables列表(dicts / sets / lists),每个包含一行的数据。
key_list: list that specifies what keys/indices to read from each row to form columns.
key_list:list,指定从每行读取哪些键/索引以形成列。
def getPrintTable(row_collection, key_list, field_sep=' '*4):
return '\n'.join([field_sep.join([str(row[col]).ljust(width)
for (col, width) in zip(key_list, [max(map(len, column_vector))
for column_vector in [ [v[k]
for v in row_collection if k in v]
for k in key_list ]])])
for row in row_collection])
#4
4
You can simply left justify the string to a certain number of characters if you want to keep it simple:
如果你想保持简单,你可以简单地将字符串左对齐为一定数量的字符:
print string1.ljust(20) + string2.ljust(20)
#5
1
You can try the Padnums module. The example output seems to match what you are requesting.
您可以尝试Padnums模块。示例输出似乎与您请求的内容相匹配。
Or this table indentation method.
或者这个表缩进方法。
I haven't used either, but they were in the first few result of googling "python pretty print table"
我没有使用过,但是他们在google搜索“python pretty print table”的前几个结果中
#1
55
Standard Python string formatting may suffice.
标准Python字符串格式化可能就足够了。
# assume that your data rows are tuples
template = "{0:8}|{1:10}|{2:15}|{3:7}|{4:10}" # column widths: 8, 10, 15, 7, 10
print template.format("CLASSID", "DEPT", "COURSE NUMBER", "AREA", "TITLE") # header
for rec in your_data_source:
print template.format(*rec)
Or
# assume that your data rows are dicts
template = "{CLASSID:8}|{DEPT:10}|{C_NUM:15}|{AREA:7}|{TITLE:10}" # same, but named
print template.format( # header
CLASSID="CLASSID", DEPT="DEPT", C_NUM="COURSE NUMBER",
AREA="AREA", TITLE="TITLE"
)
for rec in your_data_source:
print template.format(**rec)
Play with alignment, padding, and exact format specifiers to get best results.
使用对齐,填充和精确格式说明符来获得最佳结果。
#2
11
class TablePrinter(object):
"Print a list of dicts as a table"
def __init__(self, fmt, sep=' ', ul=None):
"""
@param fmt: list of tuple(heading, key, width)
heading: str, column label
key: dictionary key to value to print
width: int, column width in chars
@param sep: string, separation between columns
@param ul: string, character to underline column label, or None for no underlining
"""
super(TablePrinter,self).__init__()
self.fmt = str(sep).join('{lb}{0}:{1}{rb}'.format(key, width, lb='{', rb='}') for heading,key,width in fmt)
self.head = {key:heading for heading,key,width in fmt}
self.ul = {key:str(ul)*width for heading,key,width in fmt} if ul else None
self.width = {key:width for heading,key,width in fmt}
def row(self, data):
return self.fmt.format(**{ k:str(data.get(k,''))[:w] for k,w in self.width.iteritems() })
def __call__(self, dataList):
_r = self.row
res = [_r(data) for data in dataList]
res.insert(0, _r(self.head))
if self.ul:
res.insert(1, _r(self.ul))
return '\n'.join(res)
and in use:
并在使用中:
data = [
{'classid':'foo', 'dept':'bar', 'coursenum':'foo', 'area':'bar', 'title':'foo'},
{'classid':'yoo', 'dept':'hat', 'coursenum':'yoo', 'area':'bar', 'title':'hat'},
{'classid':'yoo'*9, 'dept':'hat'*9, 'coursenum':'yoo'*9, 'area':'bar'*9, 'title':'hathat'*9}
]
fmt = [
('ClassID', 'classid', 11),
('Dept', 'dept', 8),
('Course Number', 'coursenum', 20),
('Area', 'area', 8),
('Title', 'title', 30)
]
print( TablePrinter(fmt, ul='=')(data) )
produces
ClassID Dept Course Number Area Title
=========== ======== ==================== ======== ==============================
foo bar foo bar foo
yoo hat yoo bar hat
yooyooyooyo hathatha yooyooyooyooyooyooyo barbarba hathathathathathathathathathat
#3
4
This function takes list comprehension to a bit of an extreme, but it accomplishes what you're looking for with optimal performance:
这个函数使列表理解有点极端,但它以最佳性能完成了你正在寻找的东西:
algorithm:
- find longest field in each column; i.e., 'max(map(len, column_vector))'
- for each field (left to right, top to bottom), call str.ljust to align it to the left boundary of the column it belongs to.
- join fields with desired amount of separating whitespace (creating a row).
- join collection of rows with a newline.
在每列中找到最长的字段;即'max(map(len,column_vector))'
对于每个字段(从左到右,从上到下),调用str.ljust将其对齐到它所属列的左边界。
连接具有所需分隔空白量的字段(创建一行)。
使用换行符连接行集合。
row_collection: list of iterables (dicts/sets/lists), each containing data for one row.
row_collection:iterables列表(dicts / sets / lists),每个包含一行的数据。
key_list: list that specifies what keys/indices to read from each row to form columns.
key_list:list,指定从每行读取哪些键/索引以形成列。
def getPrintTable(row_collection, key_list, field_sep=' '*4):
return '\n'.join([field_sep.join([str(row[col]).ljust(width)
for (col, width) in zip(key_list, [max(map(len, column_vector))
for column_vector in [ [v[k]
for v in row_collection if k in v]
for k in key_list ]])])
for row in row_collection])
#4
4
You can simply left justify the string to a certain number of characters if you want to keep it simple:
如果你想保持简单,你可以简单地将字符串左对齐为一定数量的字符:
print string1.ljust(20) + string2.ljust(20)
#5
1
You can try the Padnums module. The example output seems to match what you are requesting.
您可以尝试Padnums模块。示例输出似乎与您请求的内容相匹配。
Or this table indentation method.
或者这个表缩进方法。
I haven't used either, but they were in the first few result of googling "python pretty print table"
我没有使用过,但是他们在google搜索“python pretty print table”的前几个结果中