in Datei schreiben... ARG

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Hallo!

Code: Alles auswählen

for i in range()
    text1=...
    zeile1=...
    text=text1+' * '+zeile1+' * '
Datei.write(text)
In der Schleife laufen hier mit text1 und zeile1 verschiedene Sachen ab.
Sie sollen dann beide in eine Zeile mit ein bisschen Verschönerung dazwischen geschrieben werden. Doch habe ich mir dann überlegt, dass ich doch alles hintereinander in einer Zeile haben will und habe es deshalb so umgeformt:

Code: Alles auswählen

for i in range():
    text=text+text1+' * '+zeile1+' * '
Datei.write(text)
"text" wächst hier bei jedem Schleifendurchlauf um "text1+' 1 '+zeile1+' '" an.
Ich möchte ja, dass das alles nach dem kompletten Schleifendurchlauf in die Datei in *eine* Zeile geschrieben wird.
Doch wird es das nicht. Nach "text" findet jedesmal ein Zeilenumbruch statt. Ich habe auch die beteiligten Dateitypen verändert, es hat nichts gebracht.
´
Wieso tut es das nur? :twisted:


Gruß
peak
BlackJack

Der Quelltext da oben tut gar nicht:

Code: Alles auswählen

In [46]: for i in range():
   ....:     pass
   ....:
---------------------------------------------------------------------------
<type 'exceptions.TypeError'>             Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

<type 'exceptions.TypeError'>: range expected at least 1 arguments, got 0
Wenn der echte Quelltext Zeilenumbrüche in die Datei schreibt, dann müssen in den Daten halt irgend wo Zeilenumbrüche enthalten sein. Auf "magische" Weise kommen die da nicht hinein.

Zeig doch mal ein kleines, lauffähiges Stück Quelltext mit dem Problem, so dass man das auch nachvollziehen kann.
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Natürlich funktioniert das da oben nicht; Teile funktionieren auch nicht.
Ich wollte es aber nicht so abschreckend viel aussehen lassen :)

Code: Alles auswählen

fd=open("C:\Dokumente und Einstellungen\Besitzer\Desktop\Deutsch.txt")
Indew = open("C:\Dokumente und Einstellungen\Besitzer\Desktop\Index.txt", "w")

buch=fd.readlines()

alpha=['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','Ä','Ö','Ü']
laenge=len(alpha)
zeile=buch[0]
zeilenanfang=zeile[0]+zeile[1]+zeile[2]
n=0

for i in range(laenge):
    for j in range(laenge):
        for k in range(laenge):
            text=alpha[i]+alpha[j]+alpha[k]
            if text==zeilenanfang:
                while text==zeilenanfang:
                    textw=text+' 1 '+zeile
                    Indew.write(textw)
                    n=n+1
                    zeile=buch[n]
                    zeilenanfang=zeile[0]+zeile[1]+zeile[2]
            else:
                textr=text+' 0 '+'\n'
                Indew.write(textr)
Dazu brauch man ne Textdatei, in der in jeder Zeile ein Wort in Großbuchstaben steht (Deutsch.txt) und ne leere Datei (Index.txt).
In der Index-Datei sollen später alle Kombinationen mit drei Buchstaben stehen; also:
"
AAA
AAB
AAC
...
ÜÜÜ
"
Wenn in der Deutsch.txt ein Wort mit einer dieser Kombinationen anfängt, soll auf die Kombination eine "1" folgen und danach alle zutreffenden Wörter. Wenn es kein passendes Wort gibt, soll dahinter ne "0" stehen.
Jetzt wird aber für jedes Wort eine eigenen Zeile angelegt, was ich vermeiden will.
BlackJack

Ich könnte Dir jetzt sagen wo die Zeilenumbrüche her kommen, aber vielleicht lernst Du mehr wenn Du das selber heraus findest. Lass Dir an den entscheidenden Stellen mal die Einzelteile mit ``print repr(objekt)`` anzeigen.

Ansonsten braucht man die Zeilen nicht komplett einlesen, sondern kann die Datei Zeile für Zeile abarbeiten. Damit spart man schon einmal das `n` ein.

`zeile` und `zeilenanfang` muss man auch nicht vor den Schleifen bestimmen, wenn man den Quelltext ein wenig umstellt.

Statt den `range()`\s kann man direkt über die Elemente von `alpha` iterieren. Ausserdem würde ich aus `alpha` eine Unicode-Zeichenkette machen und den Dateiinhalt auch dekodieren (`codecs.open()`). Da auch Umlaute vorkommen, funktioniert dieser Quelltext zum Beispiel nicht mehr wenn diese Zeichen mit mehr als einem Byte kodiert werden.

`zeilenanfang` lässt sich mit "slicing" kürzer schreiben.

Können Worte mit weniger als drei Zeichen vorkommen? Falls ja, verhält sich das Programm wie gewünscht?
BlackJack

Ein Lösungsansatz mit `itertools.groupby()`:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division, with_statement
import codecs
import string
from itertools import groupby


def iter_words_file(filename, encoding, min_length=3):
    """Returns iterable over upper cased words from `filename`
    that are at least `min_length` characters long.
    
    :rtype: iterable of `unicode`
    """
    with codecs.open(filename, 'rb', encoding) as lines:
        for line in lines:
            line = line.strip()
            if len(line) >= min_length:
                yield line.upper()


def iter_groups(words, index_length=3):
    """Returns an iterable over tuples of an index key and all words
    for that key separated by spaces.
    
    The `words` must be sorted.
    
    >>> words = ['foo', 'foobar', 'python', 'pythonista', 'spam']
    >>> groups = iter_groups(words)
    >>> groups.next()
    ('foo', 'foo foobar')
    >>> groups.next()
    ('pyt', 'python pythonista')
    >>> groups.next()
    ('spa', 'spam')
    """
    return ((k, ' '.join(w))
            for k, w in groupby(words, lambda word: word[:index_length]))


def main():
    alphabet = string.uppercase + u'ÄÖÜ'
    index_keys = (a + b + c
                  for a in alphabet
                  for b in alphabet
                  for c in alphabet)
    key2words = dict(iter_groups(iter_words_file('/usr/share/dict/ngerman',
                                                 'iso-8859-1')))
    for index_key in index_keys:
        print '%s %d %s' % (index_key,
                            index_key in key2words,
                            key2words.get(index_key, ''))


if __name__ == '__main__':
    main()
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Hallo!

Ich habe alles mal mit repr(obj) durchgeschaut.
Was macht dieser Befehl eigentlich?
Dabei ist mir aufgefallen, dass "zeile" immer noch ein "\n" am Ende enthält.
Deshalb habe ich versucht mit

Code: Alles auswählen

del zeile[len(zeile)]
das letzte Element (='\n') aus dem String zu löschen.
Doch gibt es diesen Befehl bei Strings nicht, deswegen habe ich ein bisschen rungesucht und bin auf

Code: Alles auswählen

zeile=zeile.replace("\n","")
gestoßen. Ist zwar nicht das Wahre, aber es funktioniert.

Danke für deine Hilfe! :D
Deine eigene Version versuche ich mal zu verstehen.
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Ach und:
"Können Worte mit weniger als drei Zeichen vorkommen? Falls ja, verhält sich das Programm wie gewünscht?"
Ja, dass dabei das Programm abbricht, habe ich schon gemerkt.
Deswegen habe ich ein anderes Programm geschrieben, das alle 2er-Wörter aus der Datei löscht. Die kann ich später sowieso nicht gebrauchen.
Dabei ist mir aufgefallen, dass zeilenlaenge=len(zeile) immer einen um 1 zu großen Wert geliefert hat. Ich dachte, dass das nen Bug oder so wäre und habe dann einfach alle Wörter mit der Länge 3 gelöscht, was dann alle mit der realen Länge von 2 gelöscht hat.
Jetzt weiß ich, dass dieser "Bug" das angehängte "\n" war :D
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Peak_me hat geschrieben: Dabei ist mir aufgefallen, dass "zeile" immer noch ein "\n" am Ende enthält.

Code: Alles auswählen

zeile = zeile[:-1]
Siehe "Strings" im Tutorial.
Peak_me
User
Beiträge: 92
Registriert: Sonntag 27. Januar 2008, 03:09

Code: Alles auswählen

zeile = zeile[:-1]
Danke, hab ich gleich eingearbeitet!
Antworten