dict als tabelle mit verbunden Zellen ausgeben...
@cofi: Soweit ich das sehe kann `prettytable` da nichts machen. `rowspan`\s kann das nicht. Und es bleibt ja immer noch das eigentliche Problem zu erkennen was zusammengefasst werden kann/muss.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ja, das ist schon nett. Aber ich sehe da nichts über verbundene Zellen...cofi hat geschrieben:Ich wuerde das Problem ja an prettytable weiterreichen.
Hier meine ziemlich dumme Lösung:
Code: Alles auswählen
class Cell(object):
def __init__(self, txt):
self.txt = txt
self.rowspan = 0
def html(self):
if self.rowspan is None:
return ""
elif self.rowspan == 1:
return "<td>%s</td>" % self.txt
return '<td rowspan="%i">%s</td>' % (self.rowspan, self.txt)
def __str__(self):
return "<'%s' rowspan=%s>" % (self.txt, self.rowspan)
__repr__ = __str__
data = [('SUB', 'SUBA', '0x80'),
('SUB', 'SUBA', '0x90'),
('SUB', 'SUBA', '0xa0'),
('SUB', 'SUBA', '0xb0'),
('SUB', 'SUBB', '0xc0'),
('SUB', 'SUBB', '0xd0'),
('SUB', 'SUBB', '0xe0'),
('SUB', 'SUBB', '0xf0'),
('SUB', 'SUBD', '0x83'),
('SUB', 'SUBD', '0x93'),
('SUB', 'SUBD', '0xa3'),
('SUB', 'SUBD', '0xb3')]
new_data = []
for row in data:
new_data.append([Cell(cell) for cell in row])
data = new_data
for colum_no in xrange(len(data[0])):
old_cell = None
same_count = 0
for row in reversed(data) :
cell = row[colum_no]
if old_cell is None:
old_cell = cell
same_count = 1
elif cell.txt == old_cell.txt:
old_cell.rowspan = None
old_cell = cell
same_count += 1
else:
old_cell.rowspan = same_count
old_cell = cell
same_count = 1
old_cell.rowspan = same_count
print "<table>"
for row in data:
print "\t<tr>"
for cell in row:
if cell.rowspan is not None:
print "\t\t%s" % cell.html()
print "\t</tr>"
print "</table>"
Zeilen 31 bis 34 kannst du kürzer schreiben als:
Und Zeilen 43, 47 und 51 solltest du hinter den if/elif/else-Block ziehen und zusammenfassen.
Code: Alles auswählen
data = [map(Cell, row) for row in data]
Das Leben ist wie ein Tennisball.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Danke für die Anregungen... Man kann auch diese zwei Schleifen zusammen fassen, wenn es keine tuple() sind:
Dennoch finde ich das recht unelegant, oder?
Code: Alles auswählen
class Cell(object):
def __init__(self, txt):
self.txt = txt
self.rowspan = 0
def html(self):
if self.rowspan is None:
return ""
elif self.rowspan == 1:
return "<td>%s</td>" % self.txt
return '<td rowspan="%i">%s</td>' % (self.rowspan, self.txt)
def __str__(self):
return "<'%s' rowspan=%s>" % (self.txt, self.rowspan)
__repr__ = __str__
data = [['SUB', 'SUBA', '0x80'],
['SUB', 'SUBA', '0x90'],
['SUB', 'SUBA', '0xa0'],
['SUB', 'SUBA', '0xb0'],
['SUB', 'SUBB', '0xc0'],
['SUB', 'SUBB', '0xd0'],
['SUB', 'SUBB', '0xe0'],
['SUB', 'SUBB', '0xf0'],
['SUB', 'SUBD', '0x83'],
['SUB', 'SUBD', '0x93'],
['SUB', 'SUBD', '0xa3'],
['SUB', 'SUBD', '0xb3']]
# Wenn es doch tuple sind:
# data = [list(row) for row in data]
for colum_no in xrange(len(data[0])):
old_cell = None
same_count = 0
for row in reversed(data):
cell = row[colum_no]=Cell(row[colum_no])
if old_cell is None:
same_count = 1
elif cell.txt == old_cell.txt:
old_cell.rowspan = None
same_count += 1
else:
old_cell.rowspan = same_count
same_count = 1
old_cell = cell
old_cell.rowspan = same_count
print "<table>"
for row in data:
print "\t<tr>"
for cell in row:
if cell.rowspan is not None:
print "\t\t%s" % cell.html()
print "\t</tr>"
print "</table>"
@jens:
Eher als Anregung - ich bau mir solche "Datenblätter" lieber als eigenständiges interaktives HTML-Dokument mit der Präsentationslogik in Javascript als festgezurrt durch ein Template. Denkbar wäre z.B. Sortierung durch Klick auf Tabellenkopf, Suchfilter oder Anzeigen von zusätzlichen Inhalten bei Klick auf einen Eintrag. Falls solche Dinge wichtig sein sollten, wirds mit der pythonseitigen Aufbereitung schwierig. Da bist Du mit dem rohen Datensatz und der Bearbeitung in Javascript besser beraten.
Eher als Anregung - ich bau mir solche "Datenblätter" lieber als eigenständiges interaktives HTML-Dokument mit der Präsentationslogik in Javascript als festgezurrt durch ein Template. Denkbar wäre z.B. Sortierung durch Klick auf Tabellenkopf, Suchfilter oder Anzeigen von zusätzlichen Inhalten bei Klick auf einen Eintrag. Falls solche Dinge wichtig sein sollten, wirds mit der pythonseitigen Aufbereitung schwierig. Da bist Du mit dem rohen Datensatz und der Bearbeitung in Javascript besser beraten.
@jens: Das hier *muss* elegent sein, denn es verwendet Rekursion. Ist aber wahrscheinlich von der Effizienz eher nicht so toll:
Code: Alles auswählen
#!/usr/bin/env python
from itertools import groupby
from operator import itemgetter
DATA = [
('SUB', 'SUBA', '0x80'),
('SUB', 'SUBA', '0x90'),
('SUB', 'SUBA', '0xa0'),
('SUB', 'SUBA', '0xb0'),
('SUB', 'SUBB', '0xc0'),
('SUB', 'SUBB', '0xd0'),
('SUB', 'SUBB', '0xe0'),
('SUB', 'SUBB', '0xf0'),
('SUB', 'SUBD', '0x83'),
('SUB', 'SUBD', '0x93'),
('SUB', 'SUBD', '0xa3'),
('SUB', 'SUBD', '0xb3'),
('ADD', 'ADDA', '0x00'),
('ADD', 'ADDA', '0x01'),
]
get_first = itemgetter(0)
def grouping(data):
if data[0]:
for key, group in groupby(data, get_first):
new_data = [row[1:] for row in group]
yield key, len(new_data), grouping(new_data)
def create_rows(grouped_data, columns=()):
for block in grouped_data:
cell, row_count, next_column = block
for column in create_rows(next_column):
yield columns + ((cell, row_count),) + column
cell, row_count = None, 0
yield ()
def create_table_rows(rows):
for row in rows:
if row and row[-1][-1]:
print '<tr>'
for value, row_count in row:
if row_count:
print ' <td rowspan="{0}">{1}</td>'.format(
row_count, value
)
print '</tr>'
def main():
grouped = list(grouping(DATA))
row_data = list(create_rows(grouped))
create_table_rows(row_data)
if __name__ == '__main__':
main()
Weder noch. Ich bin da Fan von "ein Dokument", das erleichtert die Weitergabe deutlich und ist für simple Sachen wie Tabellenmanipulation völlig ausreichend. Als Rohbau wäre vllt. die Grundstruktur zu sehen:jens hat geschrieben:Das wäre auch super. Hast du da einen Rohbau oder nutzt du ein "Framework" dafür?
Code: Alles auswählen
<html>
<head>
<title>...</title>
<style>
...
</style>
<!-- falls 2 Dokumente kein Problem sind -->
<script type="text/javascript" src="./data.js"></script>
<body>
<!-- hier Grundgerüst für Präsi -->
<script type="text/javascript">
// selbstgebauter minimaler Knotenselektor, braucht man immer ;)
function $(id) {
return document.getElementById(id);
}
// andere Helferlein wie Eventhandler etc.
...
// hier passiert die Magie, z.B. Tabelle füllen, sortieren, Ein-/Ausblenden etc.
// geht wunderbar mit $('wotever').innerHTML
function work_with_data(data) {
....
}
// hier kommen die Daten rein, wahlweise auch oben im Header
var data = ...;
work_with_data(data);
</script>
</body>
</html>