it-swarm.com.de

Python - Drucken eines Wörterbuchs als horizontale Tabelle mit Kopfzeilen

Ich habe ein Wörterbuch:

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

Ich möchte es ausdrucken, damit es gut zu Kopfzeilen passt. Kann ich die Header zum Wörterbuch hinzufügen und immer sicher sein, dass sie oben stehen? Ich habe ein paar Möglichkeiten gesehen, es vertikal zu machen, aber ich möchte, dass es mit maximalen Spaltenbreiten in der Nähe von max str () oder int () kommt.

Beispiel:

Schlüssel ________ _ ​​Label__________Nummer
1
__________ _ ​​Gewürze_________ _ ​​42
2
__________ _ ​​Sonstiges_____ _16
usw

Anscheinend kann ich das innerhalb dieses Editors nicht einmal manuell machen, aber ich hoffe, die Idee stößt auf ... Ich möchte auch nicht wirklich das _. Nur ein Platzhalter.
Vielen Dank an alle. 

22
Faller

Sie können string formatieren :

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)

Ausgabe:

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 
48

Ich suchte nach einer Lösung mit unbekannter Spaltenbreite, um eine Datenbanktabelle zu drucken. Hier ist es also:

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] or '') 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))

Probe:

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

Ausgabe:

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

Im Psycopg-Kontext können Sie es folgendermaßen verwenden:

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

Wenn Sie eine Variante für mehrzeilige Zeilen benötigen, ist dies hier:

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:
      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]

Probe:

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

Ausgabe:

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

Ohne sep-Parameter gibt printTable(sampleDict) Folgendes an:

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

Ich würde pandas DataFrame bevorzugen

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

Ausgabe:

  Name  Age
0    a   10
1    b   11
2    c   12

lesen Sie mehr über das Drucken eines hübschen Datenrahmens hier

1
Vivek Reddy

Basierend auf dem Code von Le Droid fügte ich für jede Zeile ein Trennzeichen '-' hinzu, um den Druck deutlicher zu machen. Danke, 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))

Ausgabe:

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