Seite 2 von 2

Verfasst: Dienstag 9. März 2010, 01:36
von snafu
Allerdings hat auch deine Version leider so ihre Schwächen:

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                             
[...]
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.

Verfasst: Dienstag 9. März 2010, 19:37
von bords0
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.
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...

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...

Verfasst: Dienstag 9. März 2010, 20:54
von snafu
Das Kriterium ist, möglichst gleich viele Zeilen mit den Spalten zu verbrauchen. Nur die letzte kann weniger haben, sollte aber eben nicht zu krass rausstechen. -1/-2 wäre optimal.

Verfasst: Mittwoch 10. März 2010, 07:45
von snafu
Um das nochmal zu verdeutlichen:

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
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.

Verfasst: Mittwoch 10. März 2010, 22:36
von bords0
snafu hat geschrieben:Die Priorität liegt also bei gleich großen Spalten, selbst wenn dadurch nicht der komplette Bildschirm ausgefüllt wird.
Ja, in dem Beispiel ist das einfach; das haben glaube ich alle vorgestellten Programme auch so gemacht.
Interessant wirds z.B. bei sowas: Was passiert bei 17 Dateien, wenn 6 nicht mehr nebeneinander passen, aber 5?

Verfasst: Mittwoch 10. März 2010, 23:27
von snafu
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.

Verfasst: Donnerstag 11. März 2010, 00:17
von bords0
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 ? :wink:

Ich find's aber ganz interessant... :-)

Verfasst: Donnerstag 11. März 2010, 00:28
von snafu
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:

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
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. :)

Verfasst: Samstag 13. März 2010, 19:20
von bords0
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.)