【问题标题】:Python - Printing a dictionary as a horizontal table with headersPython - 将字典打印为带有标题的水平表
【发布时间】:2013-06-24 04:28:37
【问题描述】:

我有一本字典:

import math
import random

d = {1: ["Spices", math.floor(random.gauss(40, 5))],
    2: ["Other stuff", math.floor(random.gauss(20, 5))],
    3: ["Tea", math.floor(random.gauss(50, 5))],
    10: ["Contraband", math.floor(random.gauss(1000, 5))],
    5: ["Fruit", math.floor(random.gauss(10, 5))],
    6: ["Textiles", math.floor(random.gauss(40, 5))]
}

我想把它打印出来,让它与标题很好地对齐。我可以将标题添加到字典中并始终确保它们排在首位吗? 我已经看到了几种垂直执行此操作的方法,但我希望它的最大列宽接近最大 str() 或 int()。

例子:

键___________________标签__________________号码
1____________香料___________42
2____________其他东西_____________16
等等

显然,我什至无法在此编辑器中手动执行此操作,但我希望这个想法能够实现。 我也不是真的想要__。只是一个占位符。
谢谢大家。

【问题讨论】:

  • 你有没有尝试过?想到for key in d: print('{}\t{}\t{}'.format(key, d[key][0], d[key][1]))(将:<width 添加到这些括号内的内容中)...
  • 我不想让制表符对列宽的可变性造成影响。不过我试过了。

标签: python python-3.x dictionary


【解决方案1】:

我正在寻找一种列宽未知的解决方案来打印数据库表。所以这里是:

def printTable(myDict, colList=None):
   """ Pretty print a list of dictionaries (myDict) as a dynamically sized table.
   If column names (colList) aren't specified, they will show in random order.
   Author: Thierry Husson - Use it as you want but don't blame me.
   """
   if not colList: colList = list(myDict[0].keys() if myDict else [])
   myList = [colList] # 1st row = header
   for item in myDict: myList.append([str(item[col] if item[col] is not None else '') for col in colList])
   colSize = [max(map(len,col)) for col in zip(*myList)]
   formatStr = ' | '.join(["{{:<{}}}".format(i) for i in colSize])
   myList.insert(1, ['-' * i for i in colSize]) # Seperating line
   for item in myList: print(formatStr.format(*item))

示例:

printTable([{'a':123,'bigtitle':456,'c':789},{'a':'x','bigtitle':'y','c':'z'}, \
    {'a':'2016-11-02','bigtitle':1.2,'c':78912313213123}], ['a','bigtitle','c'])

输出:

a          | bigtitle | c             
---------- | -------- | --------------
123        | 456      | 789           
x          | y        | z             
2016-11-02 | 1.2      | 78912313213123

在 Psycopg 上下文中,您可以这样使用它:

curPG.execute("SELECT field1, field2, ... fieldx FROM mytable")
printTable(curPG.fetchall(), [c.name for c in curPG.description])

如果您需要多行行的变体,这里是:

def printTable(myDict, colList=None, sep='\uFFFA'):
   """ Pretty print a list of dictionaries (myDict) as a dynamically sized table.
   If column names (colList) aren't specified, they will show in random order.
   sep: row separator. Ex: sep='\n' on Linux. Default: dummy to not split line.
   Author: Thierry Husson - Use it as you want but don't blame me.
   """
   if not colList: colList = list(myDict[0].keys() if myDict else [])
   myList = [colList] # 1st row = header
   for item in myDict: myList.append([str(item[col] or '') for col in colList])
   colSize = [max(map(len,(sep.join(col)).split(sep))) for col in zip(*myList)]
   formatStr = ' | '.join(["{{:<{}}}".format(i) for i in colSize])
   line = formatStr.replace(' | ','-+-').format(*['-' * i for i in colSize])
   item=myList.pop(0); lineDone=False
   while myList or any(item):
      if all(not i for i in item):
         item=myList.pop(0)
         if line and (sep!='\uFFFA' or not lineDone): print(line); lineDone=True
      row = [i.split(sep,1) for i in item]
      print(formatStr.format(*[i[0] for i in row]))
      item = [i[1] if len(i)>1 else '' for i in row]

示例:

sampleDict = [{'multi lines title': 12, 'bigtitle': 456, 'third column': '7 8 9'},
{'multi lines title': 'w x y z', 'bigtitle': 'b1 b2', 'third column': 'z y x'},
{'multi lines title': '2', 'bigtitle': 1.2, 'third column': 78912313213123}]

printTable(sampleDict, sep=' ')

输出:

bigtitle | multi | third         
         | lines | column        
         | title |               
---------+-------+---------------
456      | 12    | 7             
         |       | 8             
         |       | 9             
---------+-------+---------------
b1       | w     | z             
b2       | x     | y             
         | y     | x             
         | z     |               
---------+-------+---------------
1.2      | 2     | 78912313213123

没有sep参数,printTable(sampleDict)给你:

bigtitle | multi lines title | third column  
---------+-------------------+---------------
456      | 12                | 7 8 9         
b1 b2    | w x y z           | z y x         
1.2      | 2                 | 78912313213123

【讨论】:

  • 功能漂亮。
  • 不错的功能!我的数据有换行符,因为它有多行数据。假设bigtitle 列数据具有换行符,我想在该列空间内打印这些字符。有可能吗?
  • @Karthi1234 不是不到 10 行代码,但它在最后(更新)。
  • 爱它。谢谢!
  • 我发现多行行表有一个问题。当最后一行有多行时,它会停止打印第一行。要修复它,只需在 while 循环中添加或 any(item)(即 while myList or any(item):
【解决方案2】:

你可以使用string formatting in python2:

    print "{:<8} {:<15} {:<10}".format('Key','Label','Number')
    for k, v in d.iteritems():
        label, num = v
        print "{:<8} {:<15} {:<10}".format(k, label, num)

或者,string formatting in python3

    print("{:<8} {:<15} {:<10}".format('Key','Label','Number'))
    for k, v in d.items():
        label, num = v
        print("{:<8} {:<15} {:<10}".format(k, label, num))

输出:

Key      Label           Number    
1        Spices          38.0      
2        Other stuff     24.0      
3        Tea             44.0      
5        Fruit           5.0       
6        Textiles        37.0      
10       Contraband      1000.0 

【讨论】:

  • 哦。我没有意识到。谢谢。这比我预期的要容易。
  • 我有一个问题?如何使用 python 在文件中添加相同的格式。
  • 对于 Python 2.73.x,请使用 d.items() 而不是 d.iteritems()
【解决方案3】:

String formatting 提供了一个不错的简单解决方案。这个答案是来自@Ashwini 的好答案的 Python 3 更新。

str_fmt = "{:<8} {:<15} {:<10}"
print(str_fmt.format('Key','Label','Number'))
for k, v in d.items():
    label, num = v
    print(str_fmt.format(k, label, num))

【讨论】:

    【解决方案4】:

    我更喜欢 pandas DataFrame

    import pandas as pd
    data = {'Name': ['a', 'b', 'c'], 'Age': [10, 11, 12]}
    df = pd.DataFrame(data)
    print(df)
    

    输出:

      Name  Age
    0    a   10
    1    b   11
    2    c   12
    

    查看更多关于打印漂亮数据框here

    【讨论】:

    • 如果不是字典中的所有值都具有相同的长度怎么办?
    • 尝试通过填充None使字典中的所有值长度相等
    【解决方案5】:

    基于 Le Droid 的代码,我为每一行添加了分隔符“-”,可以使打印更清晰。谢谢,Le Droid。

    def printTable(myDict, colList=None):
        if not colList: 
            colList = list(myDict[0].keys() if myDict else [])
        myList = [colList] # 1st row = header
        for item in myDict: 
            myList.append([str(item[col] or '') for col in colList])
        #maximun size of the col for each element
        colSize = [max(map(len,col)) for col in zip(*myList)]
        #insert seperating line before every line, and extra one for ending. 
        for i in  range(0, len(myList)+1)[::-1]:
             myList.insert(i, ['-' * i for i in colSize])
        #two format for each content line and each seperating line
        formatStr = ' | '.join(["{{:<{}}}".format(i) for i in colSize])
        formatSep = '-+-'.join(["{{:<{}}}".format(i) for i in colSize])
        for item in myList: 
            if item[0][0] == '-':
                print(formatSep.format(*item))
            else:
                print(formatStr.format(*item))
    

    输出:

    -----------+----------+---------------
    a          | bigtitle | c             
    -----------+----------+---------------
    123        | 456      | 789           
    -----------+----------+---------------
    x          | y        | z             
    -----------+----------+---------------
    2016-11-02 | 1.2      | 78912313213123
    -----------+----------+---------------
    

    【讨论】:

      【解决方案6】:

      您可以使用 ljust 或 rjust 字符串方法:

      print key.ljust(10), label.ljust(30), number.ljust(20)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-22
        • 1970-01-01
        • 1970-01-01
        • 2019-09-19
        • 2014-01-31
        • 1970-01-01
        相关资源
        最近更新 更多