Seite 1 von 1

formatierte ausgabe von listen

Verfasst: Freitag 31. Juli 2009, 09:01
von 4bit
Hallo,

ich stecke bei dem Versuch fest mehrere Listen nacheinander mit print auszugeben, sodaß deren unterschiedlich langen elemente genau untereinander stehen.

also etwa für jede liste:

Code: Alles auswählen

print len(liste)*"%5s" % liste
danke,

4b

Verfasst: Freitag 31. Juli 2009, 09:16
von lutz.horn

Code: Alles auswählen

l1 = ["foo", "baar", "baaaz"]
l2 = ["foooo", "bar", "baaz"]

# Länge des größen Eintrags.
m = max(len(i) for i in l1 + l2)

# Listen formatiert ausgeben
for l in (l1, l2):
    print " ".join("{0:{1}}".format(i, m) for i in l)
siehe http://docs.python.org/library/string.h ... matstrings

edit: in Python 3 print() verwenden

Verfasst: Freitag 31. Juli 2009, 10:11
von 4bit
ah, ich benutze python 2.5, da gibt es die format methode noch nicht (mal updaten). ich habe die Seite, die du angegeben hast natürlich schon gesehen und gelesen, konnte aber damit nichts anfangen (vor allem, weil ich dachte, daß formatierte listen ausgeben ja nicht soo kompliziert sein kann)

hm. seltsam, daß print es einem nicht einfacher macht listen darzustellen.
gibt es vielleicht doch eine intuitivere art zum Beispiel Zeilen-Listen einer Matrix so nacheinander auszugeben, daß eine Tabelle entsteht?

Grüße,

Verfasst: Freitag 31. Juli 2009, 10:24
von lutz.horn
Ich glaube, dass mein Vorschlag recht pythonic ist, insbesondere durch die Verwendung von Generatoren. Aus der Sicht eines Python-Programmierers ist "pythonic" == "intuitiv" :)

Im Ernst: Was erscheint Dir an dieser Lösung unintuitiv?

Verfasst: Freitag 31. Juli 2009, 10:31
von 4bit
naja, eine Lste ist ja schon ein Standardobjekt und Listeneinträge untereinander als Tabelle ausgeben auch irgendwie eine Standardaufgabe. Hätte gedacht man kommt aus ohne über die Elemente zu iterieren. Aber ist ja kein Problem.

Verfasst: Freitag 31. Juli 2009, 11:00
von cofi
Nein, man muss ueber die Elemente gehen, da eine ``geprintete`` Liste die ``repr`` Darstellungen der Elemente hat.

Dein Ansatz ist fuer einen Python-Programmierer nicht intuitiv, weil sich das alles mit der Syntax von Format-Strings beisst, die eben die Argumente fuer sich aufnehmen und nicht als Template zur Darstellung einer Sequenz dienen ;)

(Vllt kann man das von Lutz auch noch besser gestalten, aber da fehlt mir grad die Muse und der Kaffee :roll:)

Verfasst: Freitag 31. Juli 2009, 12:12
von HWK
4bit hat geschrieben:ah, ich benutze python 2.5, da gibt es die format methode noch nicht (mal updaten).
Geht aber auch mit Python < 2.6:

Code: Alles auswählen

>>> print '\n'.join((' '.join('%*s' % (m, x) for x in l)) for l in (l1, l2))
  foo  baar baaaz
foooo   bar  baaz
MfG
HWK

Verfasst: Freitag 31. Juli 2009, 12:57
von mkesper
Ich hätte ja erwartet, dass jede Spalte eine eigene Länge hat.
Meine Lösung für Python < 2.6 und ohne jegliche List Comprehensions (meiner Meinung nach leichter zu lesen):

Code: Alles auswählen

results = list()
results.append(["foo", "baar", "baaaaaaaaaz"])
results.append(["foooo", "bar", "baaz"])
results.append(["fooooooooo", "bar", "baaaaaz"])

col_length = list()
for index, col in enumerate(results[0]):
    col_length.append(0)
    for row in results:
        if len(row[index]) > col_length[index]:
            col_length[index] = len(row[index])
print
for row in results:
    output = ""
    for index, col in enumerate(row):
        output = "| ".join((output, col.ljust(col_length[index] + 1)))
    output = "".join((output, "|"))    
    print output

Verfasst: Freitag 31. Juli 2009, 14:09
von EyDu
Also ich finde es mit LCs schöner:

Code: Alles auswählen

results = [
    ["foo", "baar", "baaaaaaaaaz"],
    ["foooo", "bar", "baaz"],
    ["fooooooooo", "bar", "baaaaaz"]
]

lengths = [max(map(len, x)) for x in zip(*results)]

for row in results:
    print "| ".join(col.ljust(length+1) for col, length in zip(row, lengths))
Wer gerne an den Namen spart, kann natürlich auch die ganze for-Schleife in eine LC packen ^^:

Code: Alles auswählen

print "\n".join("| ".join(v.ljust(l+1) for v, l in zip(r, ls))  for r in rs)
Natürlich sollten alle Zeilen gleich viele Elemente enthalten, sonst wird es problematisch.

Verfasst: Freitag 31. Juli 2009, 15:05
von derdon
Um es noch schöner zu machen, kannste aus lengths eine GC machen und die Funktionen itertools.imap und itertools.izip verwenden.

Verfasst: Freitag 31. Juli 2009, 15:13
von EyDu
Man kann keinen Generator für die Längen verwenden, da die Längen in der inneren for-Schleife verarbeitet werden. Mein Python 3 spart sich übrigens imap und izip. Aber wie man sieht, lege ich auch bei der älteren Version kein Werte auf den Import.