Seite 1 von 1

Umsortieren von Listen

Verfasst: Freitag 4. August 2017, 18:03
von crabnebul
Hey guys,
ich habe eine lange Liste von Wörtern in einer text file. Wenn ich die Liste direkt drucken würde, bekäme ich unmengen von Seiten. Um dies zu umgehen, würde ich gerne auf eine Seite n (~3) Spalten packen um möglichst viel Platz auszunutzen. Um das zu bewerkstelligen würde ich gerne Python benutzen. (wenn es einfacher geht ist auch gut). Der Einfachheit halber würde ich es gerne an einem kleinen Beispiel entwickeln. Angenommen ich möchte am Ende so eine Darstellung haben:
1 3 5
2 4 6
7 9 11
8 10 12
und zu begin sind meine Daten in einem array:

Code: Alles auswählen

data=range(1,13)
Wie kann ich die Datenliste so manipulieren, damit ich sie wie angegeben in eine file schreiben kann? Danke für jede Hilfe.
cs Tom

Re: Umsortieren von Listen

Verfasst: Freitag 4. August 2017, 19:07
von Sr4l
Da du range schon kennst gehe ich davon aus du kannst die Basics?

Du solltest deine Aufgabe mit for-Range und open() erledigen können.

https://docs.python.org/3/tutorial/cont ... statements

https://docs.python.org/3/tutorial/inpu ... ting-files

Re: Umsortieren von Listen

Verfasst: Freitag 4. August 2017, 19:10
von nezzcarth
Wenn du dir es einfach machen möchtest, öffne die Textdatei doch einfach mit LibreOffice Writer (oder Word) und stell bei den Seiteneinstellungen die Anzahl der Spalten auf einen entsprechend hohen Wert.

Eine andere Variante unter Linux wäre, 'column' (aus util-linux) zu nehmen.


Wenn es Python sein soll, geht es zum Beispiel in einer simplen Variante ohne Importe so:

Code: Alles auswählen

In [1]: def columnize(iterable, n=3, filler=' '):
   ...:     cache = []
   ...:     for i, item in enumerate(iterable, 1):
   ...:         cache.append(item)
   ...:         if not i % n:
   ...:             print(filler.join(cache))
   ...:             cache = []
   ...:     if cache:
   ...:         print(filler.join(cache))
   ...:         

In [2]: with open('/usr/share/dict/ngerman') as f:
   ...:     lines = [line.strip() for line in f]

Etwas kürzer geht es z.B. mit itertools.takewhile.

Re: Umsortieren von Listen

Verfasst: Freitag 4. August 2017, 20:52
von BlackJack
@nezzcarth: Schau Dir noch mal das gewünschte Muster an, so einfach ist das nicht.

Re: Umsortieren von Listen

Verfasst: Freitag 4. August 2017, 21:58
von crabnebul
Danke für deine Hilfe. Ich hab mir das Leben etwas leider gemacht und schreib jetzt einfach alles Zeile per Zeile. Mit Excel hat es auch easy geklappt wenn auch nicht sehr elegant.

Code: Alles auswählen

fo=open("final.txt","w")
#/usr/share/dict/american-english
with open('/usr/share/dict/american-english') as f:
	lines = [line.strip() for line in f]

columns=9
count =1
for item in lines:
	if (count%columns)==0:
		fo.write("\n")
		count+=1
	else:
		line = item.replace("\n"," ")
		fo.write(line+",")
		count+=1
fo.close()

Re: Umsortieren von Listen

Verfasst: Freitag 4. August 2017, 22:58
von BlackJack
@crabnebul: Die Ausgabedatei wird zu früh geöffnet. Die Reihenfolge ist ja a) Eingabedatei einlesen, b) Ausgabedatei schreiben. Also braucht man die Ausgabedatei auch nicht vor dem Lesen der Eingabedatei öffnen. Zumindest nicht wenn man die Daten vorher komplett in den Speicher liest.

Auch für die Ausgabedatei sollte man ``with`` verwenden.

`f` und `fo` sind keine guten Namen.

Die Klammern um die Modulo-Operation sind überflüssig.

Da sowohl im ``if``- als auch im ``else``-Zweig am Ende `count` hochgezählt wird, sollte das nur *einmal* hinter diesem Konstrukt stehen.

Der `replace()`-Aufruf ist sinnlos weil `item` kein '\n' mehr enthalten kann, die wurden beim Einlesen ja schon mit `strip()` entfernt.

Zwischenstand:

Code: Alles auswählen

    with open('/usr/share/dict/american-english') as in_file:
        lines = [line.strip() for line in in_file]

    with open('test.txt', 'w') as out_file:
        columns = 9
        count = 1
        for line in lines:
            if count % columns == 0:
                out_file.write('\n')
            else:
                out_file.write(line + ',')
            count += 1
Das manuelle hochzählen von `count` kann man mit `enumerate()` loswerden. Und man muss bei diesem Vorgehen gar nicht alle Zeilen in den Speicher laden (ungetestet):

Code: Alles auswählen

    with open('/usr/share/dict/american-english') as lines:
        with open('test.txt', 'w') as out_file:
            columns = 9
            for count, line in enumerate(lines, 1):
                if count % columns == 0:
                    out_file.write('\n')
                else:
                    out_file.write(line.strip() + ',')
Wenn man allerdings alles in den Speicher lädt, dann wäre eine ``for``-Schleife und „slicing“ wahrscheinlich meine Wahl (ungetestet):

Code: Alles auswählen

    with open('/usr/share/dict/american-english') as in_file:
        lines = [line.strip() for line in in_file]

    with open('test.txt', 'w') as out_file:
        columns = 9
        for i in range(0, len(lines), columns):
            out_file.write('{},\n'.format(','.join(lines[i:i + columns])))

Re: Umsortieren von Listen

Verfasst: Samstag 5. August 2017, 08:07
von nezzcarth
@BlackJack: Ich bin davon ausgegangen, dass die eigentliche Aufgabe ist, eine zeilenbasierte Datei möglichst platzsparend umzuformatieren, damit man sie gut ausdrucken kann. Da ist das konkrete Muster m.M.n. egal, solange eine eindeutige, konsistente Leserichtung erkennbar ist.

Re: Umsortieren von Listen

Verfasst: Samstag 5. August 2017, 08:34
von snafu
Vielleicht möchte man die Spaltenanfänge hübsch untereinander haben, denn bei der simplen Herangehensweise sind sie ja versetzt sobald Wörter mit unterschiedlicher Länge vorkommen. Dazu ist ein wenig mehr Aufwand nötig:

Code: Alles auswählen

from __future__ import print_function

def get_line_template(widths, sep='  '):
    if len(widths) == 0:
        return ''
    specs = ['{{:{0}.{0}}}'.format(width) for width in widths[:-1]]
    specs.append('{{:.{0}}}'.format(widths[-1]))
    return sep.join(specs)

def format_lines(lines, widths, sep='  '):
    template = get_line_template(widths, sep)
    for line_items in lines:
        try:
            yield template.format(*line_items)
        except IndexError:
            new_widths = widths[:len(line_items)]
            new_template = get_line_template(new_widths, sep)
            yield new_template.format(*line_items)

def columnize(items, num_columns, sep='  ', outfile=None):
    widths = [
        max(map(len, items[i::num_columns]))
        for i in range(num_columns)
    ]
    lines = (
        items[i : i + num_columns]
        for i in range(0, len(items), num_columns)
    )
    for line in format_lines(lines, widths, sep):
        print(line, file=outfile)

def simple_test():
    items = ['Monty', 'Python', 'Spam', 'Ham', 'Eggs', 'Parrot']
    for i in range(1, len(items)):
        columnize(items, i)
        print()

if __name__ == '__main__':
    simple_test()

Re: Umsortieren von Listen

Verfasst: Samstag 5. August 2017, 08:49
von BlackJack
Falls nezzcarth's Vermutung zutrifft würde sich vielleicht auch das `textwrap`-Modul aus der Standardbibliothek anbieten:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function
from textwrap import wrap


def main():

    with open('/usr/share/dict/american-english') as in_file:
        content = in_file.read()

    lines = wrap(content.replace('\n', ', '), width=80, break_on_hyphens=False)

    with open('test.txt', 'w') as out_file:
        out_file.writelines(line + '\n' for line in lines)


if __name__ == '__main__':
    main()
Ergebnis:
[codebox=text file=Unbenannt.txt]A, A's, AA's, AB's, ABM's, AC's, ACTH's, AI's, AIDS's, AM's, AOL, AOL's,
ASCII's, ASL's, ATM's, ATP's, AWOL's, AZ's, AZT's, Aachen, Aaliyah, Aaliyah's,
Aaron, Abbas, Abbasid, Abbott, Abbott's, Abby, Abby's, Abdul, Abdul's, Abe,
Abe's, Abel, Abel's, Abelard, Abelson, Abelson's, Aberdeen, Aberdeen's,
Abernathy, Abernathy's, Abidjan, Abidjan's, Abigail, Abilene, Abner, Abner's,
Abraham, Abraham's, Abram, Abram's, Abrams, Absalom, Abuja, Abyssinia,
Abyssinia's, Abyssinian, Abyssinian's, Ac, Ac's, Acadia, Acadia's, Acapulco,

zit's, zither, zither's, zithers, zits, zodiac, zodiac's, zodiacal, zodiacs,
zombi, zombi's, zombie, zombie's, zombies, zombis, zonal, zone, zone's, zoned,
zones, zoning, zonked, zoo, zoo's, zoological, zoologist, zoologist's,
zoologists, zoology, zoology's, zoom, zoom's, zoomed, zooming, zooms, zoos,
zucchini, zucchini's, zucchinis, zwieback, zwieback's, zygote, zygote's,
zygotes, Ångström, éclair, éclair's, éclairs, éclat, éclat's, élan,
élan's, émigré, émigré's, émigrés, épée, épée's, épées, étude,
étude's, études,[/code]