@snafu:
Für prettytable mußt Du doch vorher schon die Spaltenaufteilung kennen, oder?
Für csv ist das eine schöne Sache, mit curses kannst Du gleich mal Multiplan nachbauen
@mkesper:
Ja, das geht mit locale, liefert aber meines Wissens nach nur eine der möglichen Sortiernormen.
Wobei ich das dann eher mit sorted(['zum', 'sortieren'], key=locale.strxfrm) machen würde.
Ausgabe in Spalten wie beim Befehl "ls"
Sorry, ich hab diesen Beitrag wohl übersehen...
Nö, man jagt die Inhalte in die Klasse und hofft, dass die Terminalemulation breit genug für eine vernünftige Ausgabe ist. ;Pjerch hat geschrieben:@snafu:
Für prettytable mußt Du doch vorher schon die Spaltenaufteilung kennen, oder?
Naja, von ``curses`` hab ich auch nicht gesprochen.jerch hat geschrieben:Für csv ist das eine schöne Sache, mit curses kannst Du gleich mal Multiplan nachbauen
Was macht prettytable denn mit einer Liste? Hatte es mir nicht näher angeschaut...snafu hat geschrieben:Nö, man jagt die Inhalte in die Klasse und hofft, dass die Terminalemulation breit genug für eine vernünftige Ausgabe ist. ;P
Da hab ich wohl die Ironietags vergessensnafu hat geschrieben:Naja, von ``curses`` hab ich auch nicht gesprochen.
Grüße jerch
Ach, ich hab dich vermutlich missverstanden. Ja, du musst vorher Feldnamen vergeben, womit für PT dann auch die Anzahl der Spalten fest steht.
Insgesamt ist die Bedienung im Detail aber doch nicht so ganz das, was man von einem guten Tool erwarten würde. Gefühlt bestehen außerdem mindestens 50% des Codes aus "privaten" Getter-/Setter-Funktionen & Fehlerbehandlung. Irgendwie ist das alles schon etwas wirsch gemacht.
Der Autor hat das Projekt auch circa ein 3/4 Jahr nicht mehr angefasst, obwohl den "Issues" nach zu urteilen durchaus ein paar Leute Interesse an dem Projekt haben. Mal sehen, ob sich da noch was tut. Die Standardausgabe finde ich jedenfalls ganz nett gemacht für Fälle, wo man sich mal schnell einen Überblick über eine tabellenartige Struktur verschaffen möchte.
Insgesamt ist die Bedienung im Detail aber doch nicht so ganz das, was man von einem guten Tool erwarten würde. Gefühlt bestehen außerdem mindestens 50% des Codes aus "privaten" Getter-/Setter-Funktionen & Fehlerbehandlung. Irgendwie ist das alles schon etwas wirsch gemacht.
Der Autor hat das Projekt auch circa ein 3/4 Jahr nicht mehr angefasst, obwohl den "Issues" nach zu urteilen durchaus ein paar Leute Interesse an dem Projekt haben. Mal sehen, ob sich da noch was tut. Die Standardausgabe finde ich jedenfalls ganz nett gemacht für Fälle, wo man sich mal schnell einen Überblick über eine tabellenartige Struktur verschaffen möchte.
@sma, HWK:
Ich weiß nicht, ob das Absicht ist, aber eure Programme liefern nicht immer die geringste Zeilenanzahl. Versucht es mal mit, da kommen bei euch 6 Zeilen raus:
Es geht aber auch mit 5 Zeilen, nämlich:
(Das liegt daran, dass es zwei Möglichkeiten mit 4 Spalten gibt, und ihr untersucht in diesem Fall nur die, die nicht klappt...)
Außerdem brecht ihr ab, sobald es nicht mehr klappt, das führt bei zu , obwohl möglich ist.
So, jetzt aber der Code (im Nachhinein eigentlich straight-forward )
Ich weiß nicht, ob das Absicht ist, aber eure Programme liefern nicht immer die geringste Zeilenanzahl. Versucht es mal mit
Code: Alles auswählen
['x' * 14] * 5 + ['x' * 6] * 11
Code: Alles auswählen
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxx
Code: Alles auswählen
xxxxxxxxxxxxxx xxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
xxxxxxxxxxxxxx xxxxxx xxxxxx
Außerdem brecht ihr ab, sobald es nicht mehr klappt, das führt bei
Code: Alles auswählen
['x', 'x', 'x' * 20, 'x' * 20, 'x', 'x']
Code: Alles auswählen
x
x
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxx
x
x
Code: Alles auswählen
x xxxxxxxxxxxxxxxxxxxx x
x xxxxxxxxxxxxxxxxxxxx x
So, jetzt aber der Code (im Nachhinein eigentlich straight-forward )
Code: Alles auswählen
def table(seq, sep=" ", line_len=40):
num_items = len(seq)
col_lens = sorted(set(num_items // (i + 1) for i in range(num_items)))
for col_len in col_lens:
cols = [seq[i:i + col_len] for i in range(0, num_items, col_len)]
col_widths = [max(map(len, col)) for col in cols]
width = sum(col_widths) + len(sep) * (len(cols) - 1)
if width < line_len:
break
else:
raise ValueError("Won't fit")
cols[-1].extend([""] * (col_len - len(cols[-1])))
cols = [[item.ljust(w) for item in col] for w, col in zip(col_widths, cols)]
rows = zip(*cols)
return "\n".join(sep.join(row) for row in rows)
Allerdings hat auch deine Version leider so ihre Schwächen:
Grundlage war das. Es folgte tatsächlich noch eine ganze Reihe weiterer Zeilen und in der dritten Spalte dann die einzelne Datei. Ziel ist aber, eine optimale Aufteilung, d.h. möglichst gleich große Spalten, zu haben. Natürlich immer unter Beachtung der Maximalbreite.
Code: Alles auswählen
In [1]: import os; from columnize import columnize
In [2]: print columnize(os.listdir('.'))
------> print(columnize(os.listdir('.')))
test.pyc teleopti.py~ plan.py
simplecsv.py Desktop
Vorlagen schedule.py~
Videos bin
.nautilus schedule.png
.xsession-errors .local
.macromedia schedule-ie.png
test.csv columnize.py~
.pulse-cookie .xine
[...]
Oh. Ich vermutete, das Ziel war möglichst wenig Zeilen zu gebrauchen, und dass nur die letzte Spalte kürzer sein soll. Da kenne ich "ls" wohl nicht gut genug - habe keinen GNU zur Hand...snafu hat geschrieben:Ziel ist aber, eine optimale Aufteilung, d.h. möglichst gleich große Spalten, zu haben. Natürlich immer unter Beachtung der Maximalbreite.
Wie ist denn genau das Kriterium? Jede Spalte höchstens so lang wie die vorhergehende, und jede höchstens eins kürzer als die erste? Dann ist das wohl was ganz anderes...
Um das nochmal zu verdeutlichen:
Die Priorität liegt also bei gleich großen Spalten, selbst wenn dadurch nicht der komplette Bildschirm ausgefüllt wird. Zunächst werden die Namen nebeneinander sortiert und sobald mehrere Zeilen nötig werden, geschieht die Sortierung spaltenweise, d.h. untereinander.
Wer `touch` nicht kennt: `touch` legt Dateien an bzw erneuert den Zeitstempel bei vorhandenen Dateien.
Code: Alles auswählen
urx@murx:~/test$ touch a b c
urx@murx:~/test$ ls
a b c
urx@murx:~/test$ touch a b c d e f g h i j k l m n o p q r s t u v w x y z
urx@murx:~/test$ ls
a b c d e f g h i j k l m n o p q r s t u v w x y z
urx@murx:~/test$ touch a1
urx@murx:~/test$ ls
a b d f h j l n p r t v x z
a1 c e g i k m o q s u w y
Wer `touch` nicht kennt: `touch` legt Dateien an bzw erneuert den Zeitstempel bei vorhandenen Dateien.
Ja, in dem Beispiel ist das einfach; das haben glaube ich alle vorgestellten Programme auch so gemacht.snafu hat geschrieben:Die Priorität liegt also bei gleich großen Spalten, selbst wenn dadurch nicht der komplette Bildschirm ausgefüllt wird.
Interessant wirds z.B. bei sowas: Was passiert bei 17 Dateien, wenn 6 nicht mehr nebeneinander passen, aber 5?
Da macht ls: 4x4 (also gleich große) + 1 Zeile in der letzten Spalte. Okay, 6+6+5 wäre auch gegangen. Die Priorität ist wohl eher, möglichst wenig Zeilen zu verbrauchen und nur bei der letzten Spalte eine andere Zeilenzahl zu haben.
Ok, dann müsste eigentlich passen, was columnize macht.
Schafft ls in dem von dir zitierten Fall, wo columnize die echt ziemlich unschöne Ausgabe liefert, was vernünftiges? Oder gehen dir die blöden Fragen auf die Nerven ?
Ich find's aber ganz interessant...
Schafft ls in dem von dir zitierten Fall, wo columnize die echt ziemlich unschöne Ausgabe liefert, was vernünftiges? Oder gehen dir die blöden Fragen auf die Nerven ?
Ich find's aber ganz interessant...
Ich find's auch interessant, sonst hätt ich den Thread nicht gemacht... Ich habe die Ausgabe von deiner Funktion direkt im selben Verzeichnis mit ls verglichen und ls bringt in gewissen Fällen immer mal eine Spalte mehr unter als deine Funktion. Zum ausgiebigen Testen solltest du dir wohl eine Windows-Version von ls installieren, da das Frage-Antwort-Spiel zwar nicht direkt nervig, aber doch recht ineffektiv ist.
Ich habe jetzt mal eine objektorientierte Implementierung angefangen, die den Vorstellungen aber bisher nur rudimentär entspricht. Es ging mir dort erstmal um die Lesbarkeit und weniger um Geschwindigkeit, da ich durch die bisher gezeigten Funktionen kaum durchgeblickt habe und sie auch nicht sonderlich schön fand. Das habe ich bis jetzt:
Werde das erstmal so belassen, da ich morgen leider früh raus muss. TODO ist halt, die Spaltenbreite einheitlich zu bekommen unter der Beachtung, dass einzelne Elemente dann in die nächste Spalte rutschen können und sich damit wieder alles nachfolgende ändert. Wenn man das Glück hat, dass der längste Eintrag ziemlich am Schluss ist, hat man sicher noch mehr Spass.
Ich habe jetzt mal eine objektorientierte Implementierung angefangen, die den Vorstellungen aber bisher nur rudimentär entspricht. Es ging mir dort erstmal um die Lesbarkeit und weniger um Geschwindigkeit, da ich durch die bisher gezeigten Funktionen kaum durchgeblickt habe und sie auch nicht sonderlich schön fand. Das habe ich bis jetzt:
Code: Alles auswählen
from curses import setupterm, tigetnum
class Columnizer(object):
def __init__(self, indent=2, width=None):
self.spacer = indent * ' '
self.width = width
def drop_overage(self, strings):
if self.width is None:
setupterm()
width = tigetnum('cols')
else:
width = self.width
while len(self.spacer.join(strings)) > width:
strings = strings[:-1]
return strings
def make_lines(self, strings):
lines = []
while strings:
remaining = self.drop_overage(strings)
lines.append(remaining)
strings = strings[len(remaining):]
return lines
Das Verhalten von ls ist mir zu ungenau spezifiziert. Ich glaube, es wäre sinnvoller, wenn du einfach deine eigenen Prioritäten umsetzt, als genau auf ls zu achten.
(Wie ls allerdings mehr Spalten unterbringen kann als columnize, verstehe ich nicht.)
(Wie ls allerdings mehr Spalten unterbringen kann als columnize, verstehe ich nicht.)