web-dev-qa-db-fra.com

Python - Impression d'un dictionnaire sous forme de tableau horizontal avec en-têtes

J'ai un dictionnaire:

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

Je veux l'imprimer pour qu'il soit bien aligné avec les en-têtes. Puis-je ajouter les en-têtes au dictionnaire et être toujours sûr qu'ils arrivent en tête? J'ai vu plusieurs façons de le faire verticalement, mais j'aimerais qu'il soit fourni avec des largeurs de colonne maximales proches de max (max) str () ou int ().

Exemple:

Touche __ ___ ___Label _ ​​_ ___ ___ ___Numéro
1
_ ​​_ ___ ___ ___Épices _ ​​_ ___ ___ __42
2
_ ​​_ ___ ___ ___Autres commandes _ ​​_ _____ 16
etc

Apparemment, je ne peux même pas le faire manuellement dans cet éditeur, mais j'espère que l'idée me vient à l'esprit… .. Je ne veux pas non plus le __ non plus. Juste un remplaçant.
Merci a tous. 

22
Faller

Vous pouvez utiliser format de chaîne :

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)

Sortie:

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
Ashwini Chaudhary

Je cherchais une solution avec une largeur de colonnes inconnue pour imprimer une table de base de données. Alors la voici:

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

Échantillon:

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

Sortie:

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

Dans le contexte de Psycopg, vous pouvez l’utiliser de la manière suivante:

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

Si vous avez besoin d'une variante pour les lignes multi-lignes, la voici:

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]

Échantillon:

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

Sortie:

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

Sans le paramètre sep, printTable(sampleDict) vous donne:

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

Basé sur le code de Le Droid, j'ai ajouté un séparateur '-' pour chaque ligne, ce qui pourrait rendre l'impression plus claire. Merci, 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))

Sortie:

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