Seite 1 von 2

Verfasst: Donnerstag 25. Januar 2007, 20:53
von sape
Unser philosophischer Gerold :D

Deine Analogie mit einem Bild malen ist schön :) Ich vergleiche es auch immer gerne mit dem komponieren eines Stückes.

lg

Verfasst: Freitag 26. Januar 2007, 08:32
von lhorn
Hier noch ein funktionaler Ansatz. Bis auf die Benennung der Ausgabedateien funktioniert es. Lisp wäre hier natürlich lesbarer :wink:

Code: Alles auswählen

#!/usr/bin/env python

step = 3

lines = open("in.txt").readlines()

map(lambda p: open("out%s.txt" % p[0].strip(), "w").writelines(p),
    [lines[s:e] for s, e in
     zip(range(0, len(lines), step),
         range(step, len(lines) + step, step))])

Verfasst: Freitag 26. Januar 2007, 09:10
von gerold
lhorn hat geschrieben:

Code: Alles auswählen

#!/usr/bin/env python

step = 3

lines = open("in.txt").readlines()

map(lambda p: open("out%s.txt" % p[0].strip(), "w").writelines(p),
    [lines[s:e] for s, e in
     zip(range(0, len(lines), step),
         range(step, len(lines) + step, step))])
Hi lhorn!

Nett, wirklich nett. :twisted: Ich hatte allerdings ein paar Schwierigkeiten das Programm zu analysieren.

Was so ein paar Zeilenumbrüche und Einrückungen ausmachen:

Code: Alles auswählen

#!/usr/bin/env python

step = 3

lines = open("in.txt").readlines()

map(
    lambda p: open("out%s.txt" % p[0].strip(), "w").writelines(p),
    [
        lines[s:e] for s, e in zip(
            range(0, len(lines), step),
            range(step, len(lines) + step, step)
        )
    ]
)
...so war es ziemlich schnell durchschaubar.

lg
Gerold
:-)

Verfasst: Freitag 26. Januar 2007, 09:15
von sape
FL ist schön, aber dein Ansatz ist ein wenig inkonsistent. Die Streams werden nicht wehrende der Laufzeit des Processes geschlossen (Wenn sie nicht mehr benötigt werden) sondern erst wen er terminiert ist. Da ist bei einem Konsolenprogramm, das sich selbständig beendet, ok. Was machst du aber bei einem Konsollenprogramm/GUI-Programm das solange läuft bis es vom Benutzer beendet wird? Wohl möglich führt der Benutzer diese Funktion öfter aus? Und spätestens dann hast du ein Problem.

Ansonsten angenehm zu Lesen uns schön kurz :)

lg

Verfasst: Freitag 26. Januar 2007, 09:29
von lhorn
An die Streams habe ich auch gedacht. Ich verwende diese Art von Programm fast ausschließlich von der Konsole aus. Benutzerinteraktion findet keine statt und ich weiß auch vorher, wie groß Ein- und Ausgabe sein werden. Ich habe die Umgebung also unter Kontrolle.

Das Arbeiten mit Ein- und Ausgabe ist ja in der funkionalen Programmierung ohnehin nicht so prickelnd. Man handelt sich dabei halt leider immer Nebewirkungen ein, die sich nicht allein als Funktion der Eingabe ergeben.

Ganz funktional ist mein Versuch ja sowieso nicht. Eigentlich müsste ich die Zeilen der einzulesenden Datei inline in den beiden range-Aufrufen und beim Slice-Operator funktional ermitteln. Aber dreimal die selbe Datei einzulesen erschien mir als übertrieben :wink:

Verfasst: Freitag 26. Januar 2007, 09:33
von lhorn
gerold hat geschrieben:Was so ein paar Zeilenumbrüche und Einrückungen ausmachen
In der Tat, meine Fassung ist etwas arg kondensiert. Das liegt aber daran, dass ich sie von den inneren Funktionen her geschrieben und erst nachträglich Zeilenumbrüche eingefügt habe. Emacs denkt dabei eher an ein Lisp-artiges Layout. Seid froh, dass ich nicht meine erste funktionierende Version, die im Kern nur aus einer Zeile bestand, gepostet habe :)

Verfasst: Freitag 26. Januar 2007, 09:34
von sape
Ja, dann ist alles i.O. Bisher die kürzeste Variante (Wenn man es genau nimmt ist es ja ein Dreizeiler.).

@Gerold:
Dein zweites paste gefällt mir besser als dein erstes, weil du da über ``itertools.count`` iterierst anstatt ``while`` zu nutzen.

lg

Verfasst: Freitag 26. Januar 2007, 16:29
von lukasmarti
Zuerst mal: Danke für die vielen Antworten :D

Code: Alles auswählen

linecounter = 0 
outcounter = 0 
out = None 

for line in open("in.txt"): 
    if linecounter % 3 == 0: 
        try: 
            out.close() 
        except: 
            pass 
        out = open("out%d.txt" % outcounter, "w") 
        outcounter += 1 
    out.write("""das ist linie 1: "+line1
                  """das ist linie 2: "+line2
                  """das ist linie 3: "+line3""")
    linecounter += 1 

try: 
    out.close 
except: 
    pass 


Aber wie muss ich das noch ändern, damit es in die txt noch etwas dazuschreibt?
also:

1.txt
[Das ist linie1: (linie 1 von txt)
das ist linie2: (linie 2 von txt)
das ist linie3: (linie 3 von txt)]

2.txt
[das ist linie1: (linie 4 von txt)
das ist linie2: (linie 5 von txt)
das ist linie3: (linie 6 von txt)]
u.s.w.
das linie1, linie2 und linie3 muss sich aber nicht ändern.

Sorry das ich noch so viele Nachfragen stellen muss, aber dies überschreitet meine Fähigkeiten in Python.

Verfasst: Freitag 26. Januar 2007, 17:11
von Bernhard
Sorry, das ich nachfragen muss: Aber was genau willst Du jetzt noch dazu schreiben? Die eckigen Klammern?
Ist jetzt nicht böse, ich verstehe es wirklich nicht.

Bernhard

Edit: Willst Du eine Zeile einfügen, in der die Nummer des txt-Files steht? Also Dein "1. txt", "2. txt", ... ? Diese Information steckt in der Variable outcounter, die jeweils in Zeile 12 hochgezählt wird.

Den Inhalt ausgeben kannst Du, indem Du die Ausgabe in den Zeilen 13 bis 15 anpasst. Zum Beispiel so:

Code: Alles auswählen

        out.write( str(outcounter+1) + ". txt\ndas ist linie 1: "+line1+
                                            "\ndas ist linie 2: "+line2+
                                            "\ndas ist linie 3: "+line3 )
War es das, was Du meintest?

Verfasst: Freitag 26. Januar 2007, 20:16
von BlackJack
Ich möchte gerne anmerken, dass man `line` nicht mit `linie` sondern `Zeile` übersetzt. Sieht ja schrecklich aus… :-)

Verfasst: Samstag 27. Januar 2007, 15:02
von lukasmarti
Wenn das die txt ist:

Code: Alles auswählen

hallo
wie 
geht
es 
dir
heute 
sollen die txt am schluss so aussehen:

1.txt

Code: Alles auswählen

das ist zeile 1:hallo
das ist zeile 2: wie 
das ist zeile 3: geht
2.txt

Code: Alles auswählen

das ist zeile 1: es 
das ist zeile 2: die
das ist zeile 3: heute
Bei euren Forschlag werden die 3 Zeilen ja in der Variablen "line" gespeichert oder ?

ich muss aber die drei zeilen in verschiedene teile der txt hineinschreiben.

die stadart txt muss so aussehen:

Code: Alles auswählen

das ist zeile 1: 
das ist zeile 2: 
das ist zeile 3:
und dann jeweils immer am Ende der zeile in den neuen txts die nächste zeile der ausgangs txt zu schreiben.

Edit (Leonidas): Code-Highlighting abgeschaltet. Wow, das erste mal.

Verfasst: Samstag 27. Januar 2007, 22:35
von Leonidas
Ich hätte das anzubieten:

Code: Alles auswählen

#!/usr/bin/env python
#! -*- coding: UTF-8 -*-
from __future__ import with_statement
from contextlib import closing

def main():
    template = file('template.txt', 'r')
    templatelines = [line.strip() for line in template.readlines()]
    template.close()

    filecounter = 1
    with closing(file('input.txt', 'r')) as f_in:
        for number, line in enumerate(f_in):
            f_out = file('%s.txt' % filecounter, 'a')
            template_current = number % len(templatelines)
            f_out.write(templatelines[template_current])
            f_out.write(line)
            f_out.close()

            if template_current == len(templatelines) - 1:
                filecounter += 1

if __name__ == '__main__':
    main()
(Achtung, das produziert relativ viel IO, weil es die Datei immer für eine Zeile öffnet, ist aber vergleichsweise flexibel, weil es mit beliebig langen Input und beliebig langen Templates zurecht kommt. Tuning bleibt dem Leser überlassen)

Verfasst: Montag 29. Januar 2007, 10:40
von Bernhard
@lukasmarti:
Die Textzeilen stecken nicht in einer Variablen line, sondern in den drei Variablen line1, line2 und line3. Was ich glaube, was Du gerne möchtest, das tut das Script jetzt schon. Die Texte in den Anführungszeichen ("das ist linie 1", etc.) werden vor den jeweiligen Textzeilen ausgegeben!?

(Leonidas' Lösung macht das über ein eigenes File template.txt, in dem er die Zusätze getrennt von der Programmlogik unterbringt.)

Gruß,
Bernhard