Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python create html table from dict

Tags:

python

I´m just starting learning python and therefore like to create a html table based on filenames. Imaging following files

apple.good.2.svg
apple.good.1.svg
banana.1.ugly.svg
banana.bad.2.svg
kiwi.good.svg

The kind of object is always the first part (before the first dot) the quality property is somewhere in the name.

My resulting table should look like this:

Object Name    |       good       |       bad       |       ugly
-------------------------------------------------------------------------
apple          | apple.good.1.svg |
               | apple.good.2.svg |
-------------------------------------------------------------------------
banana         |                  | banana.bad.2.svg | banana.1.ugly.svg
-------------------------------------------------------------------------
kiwi           | kiwi.good.svg
-------------------------------------------------------------------------

This is what I did so far

#!/usr/bin/python
import glob
from collections import defaultdict

fileNames = defaultdict(list)

# fill sorted list of tables based on svg filenames
svgFiles = sorted(glob.glob('*.svg'))
for s in svgFiles: 
    fileNames[s.split('.', 1)[0]].append(s)        

# write to html
html = '<html><table border="1"><tr><th>A</th><th>' + '</th><th>'.join(dict(fileNames).keys()) + '</th></tr>'

for row in zip(*dict(fileNames).values()):
    html += '<tr><td>Object Name</td><td>' + '</td><td>'.join(row) + '</td></tr>'

html += '</table></html>'

file_ = open('result.html', 'w')
file_.write(html)
file_.close()

I managed to read the files sorted in a dict:

{'kiwi': ['kiwi.good.svg'], 'apple': ['apple.good.2.svg', 'apple.good.1.svg'], 'banana': ['banana.1.ugly.svg', 'banana.bad.2.svg']}

But fail by generating the html table.

enter image description here

How can I build the html table as shown above? Where Objects are written to the first first column of a row and the filename in columns depending on their quality property?

like image 579
Anatol Avatar asked Sep 09 '16 13:09

Anatol


People also ask

How do you insert a table in HTML?

An HTML table is created with an opening <table> tag and a closing </table> tag. Inside these tags, data is organized into rows and columns by using opening and closing table row <tr> tags and opening and closing table data <td> tags. Table row <tr> tags are used to create a row of data.


1 Answers

You have to iterate all combinations of fruits from your dictionaries and states, and then create one line (instead of one column) for each fruit. Then just iterate all the files matching that fruit and filter those that contain the current state and join those in one cell.

d = {'kiwi': ['kiwi.good.svg'], 'apple': ['apple.good.2.svg', 'apple.good.1.svg'], 'banana': ['banana.1.ugly.svg', 'banana.bad.2.svg']}

html = """<html><table border="1">
<tr><th>Object</th><th>Good</th><th>Bad</th><th>Ugly</th></tr>"""
for fruit in d:
    html += "<tr><td>{}</td>".format(fruit)
    for state in "good", "bad", "ugly":
        html += "<td>{}</td>".format('<br>'.join(f for f in d[fruit] if ".{}.".format(state) in f))
    html += "</tr>"
html += "</table></html>"

Result:

enter image description here


Update: If you have state expressions that are part of other states, like bad and medium_bad, then just using in won't work. Instead, you can use a regular expression to get the best match.

>>> fruit = "banana_bad.svg", "banana_medium_bad.svg"
>>> [re.search(r"[._](good|bad|medium_bad|ugly)[._]", f).group(1) for f in fruit]
['bad', 'medium_bad']

You could use this code then:

d = {'kiwi': ['kiwi.good.svg', 'kiwi_medium_bad.svg'], 'apple': ['apple.good.2.svg', 'apple.good.1.svg'], 'banana': ['banana.1.ugly.svg', 'banana.bad.2.svg']}
states = ['good', 'bad', 'medium_bad', 'ugly']

html = """<html><table border="1">
<tr><th>Object</th><th>{}</th></tr>""".format("</th><th>".join(states))
for fruit in d:
    html += "<tr><td>{}</td>".format(fruit)
    by_state = {f: re.search(r"[._]({})[._]".format('|'.join(states)), f).group(1) for f in d[fruit]}
    for state in states:
        html += "<td>{}</td>".format('<br>'.join(f for f in d[fruit] if by_state[f] == state))
    html += "</tr>"
html += "</table></html>"

Alternatively, you could also restructure your dictionary to have another "layer" of states, i.e. {"kiwi": {"good": ["kiwi.goog.svg"]}, ...}


If you want to wrap the filenames within image tags, you can put another format within the join:

html += "<td>{}</td>".format('<br>'.join('<img src="{}">'.format(f) for f in d[fruit] if by_state[f] == state))
like image 200
tobias_k Avatar answered Oct 09 '22 07:10

tobias_k