Как напечатать «милый» вывод строки в Python - PullRequest
27 голосов
/ 23 февраля 2011

У меня есть список dicts с полями classid, dept, coursenum, area и title из SQL-запроса. Я хотел бы вывести значения в удобочитаемом формате. Я думал о заголовке столбца в верхней части каждого, а затем в каждом столбце выводился соответствующий ответ, т.е.:

CLASSID     DEPT     COURSE NUMBER        AREA     TITLE
foo         bar      foo                  bar      foo
yoo         hat      yoo                  bar      hat

(очевидно, со стандартным выравниванием / интервалом)

Как бы я сделал это в Python?

Ответы [ 4 ]

57 голосов
/ 23 февраля 2011

Стандартное форматирование строки 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)

Или

# 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)

Играйте с указателями выравнивания, заполнения и точного формата, чтобы получить наилучшие результаты.

11 голосов
/ 23 февраля 2011
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)

и используется:

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) )

производит

ClassID     Dept     Course Number        Area     Title                         
=========== ======== ==================== ======== ==============================
foo         bar      foo                  bar      foo                           
yoo         hat      yoo                  bar      hat                           
yooyooyooyo hathatha yooyooyooyooyooyooyo barbarba hathathathathathathathathathat
5 голосов
/ 31 мая 2013

Вы можете просто выровнять строку по левому краю на определенное количество символов, если хотите, чтобы она была простой:

print string1.ljust(20) + string2.ljust(20)
4 голосов
/ 01 декабря 2012

Эта функция немного упрощает понимание списка, но она выполняет то, что вы ищете, с оптимальной производительностью:

алгоритм:

  1. найти самое длинное поле в каждомколонка;то есть 'max (map (len, column_vector))'
  2. для каждого поля (слева направо, сверху вниз), вызовите str.ljust, чтобы выровнять его по левой границе столбца, которому он принадлежит.
  3. объединение полей с необходимым количеством разделяющих пробелов (создание строки).
  4. объединение коллекций строк с новой строкой.

row_collection: список итераций (dicts/ sets / lists), каждая из которых содержит данные для одной строки.

key_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])
...