I have a dictionary:
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))]
}
I want to print it out so it lines up nicely with headers. Can I add the headers to the dictionary and always be sure they come out on top?
I’ve seen a few ways to do it vertically but I’d like to have it come out with max column widths close to the max str() or int().
Example:
Key___________________Label______________________Number
1______________________Spices_____________________42
2______________________Other Stuff_____________16
etc
Apparently I can’t even do this inside of this editor manually, but I hope the idea comes across.
I also don’t really want the __ either. Just a place holder.
Thanks all.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You can use 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)
Or, 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))
Output:
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
Method 2
I was looking for a solution with unknown columns width to print a database table. So here it is:
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))
Sample:
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'])
Output:
a | bigtitle | c ---------- | -------- | -------------- 123 | 456 | 789 x | y | z 2016-11-02 | 1.2 | 78912313213123
In Psycopg context, you can use it this way:
curPG.execute("SELECT field1, field2, ... fieldx FROM mytable")
printTable(curPG.fetchall(), [c.name for c in curPG.description])
If you need a variant for multi-lines rows, here it is:
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]
Sample:
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=' ')
Output:
bigtitle | multi | third
| lines | column
| title |
---------+-------+---------------
456 | 12 | 7
| | 8
| | 9
---------+-------+---------------
b1 | w | z
b2 | x | y
| y | x
| z |
---------+-------+---------------
1.2 | 2 | 78912313213123
Without sep parameter, printTable(sampleDict) gives you:
bigtitle | multi lines title | third column ---------+-------------------+--------------- 456 | 12 | 7 8 9 b1 b2 | w x y z | z y x 1.2 | 2 | 78912313213123
Method 3
I would prefer pandas DataFrame
import pandas as pd
data = {'Name': ['a', 'b', 'c'], 'Age': [10, 11, 12]}
df = pd.DataFrame(data)
print(df)
Output:
Name Age 0 a 10 1 b 11 2 c 12
check out more about printing pretty a dataframe here
Method 4
String formatting provides a nice, simple solution. This answer is an update for Python 3 of the nice answer from @Ashwini.
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))
Method 5
Based on Le Droid’s code, I added separator ‘-‘ for each row which could make the print more clear. Thanks, 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))
Output:
-----------+----------+--------------- a | bigtitle | c -----------+----------+--------------- 123 | 456 | 789 -----------+----------+--------------- x | y | z -----------+----------+--------------- 2016-11-02 | 1.2 | 78912313213123 -----------+----------+---------------
Method 6
I would always use pandas to print the table-type structure neatly.
It is straightforward to create a pandas dataframe from your data structure.
df = pd.DataFrame(
[[key] + list(value) for key, value in d.items()],
columns=['Key', 'Label', 'Number']
)
columns is used to define the names you would want to give to the individual columns of data.
Then, you can print it (ignoring the pandas dataframe index) as:
print(df.to_string(index=False))
Your output will print as:
Key Label Number 1 Spices 40 2 Other stuff 14 3 Tea 52 10 Contraband 992
Method 7
You can use ljust or rjust string methods:
print key.ljust(10), label.ljust(30), number.ljust(20)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0