Suchwort aus Liste in Zeile von datei finden.

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
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

Hallo,

Mein Vorhaben:
Ich habe eine Liste mit Wörtern in einer Liste.txt Datei.
Z.b.:
hund
Katze
Maus
Esel
Elefant
...
...
...
Und eine Weitere Liste mit Sätzen. Satz.txt
Z.b:
Maus ist klein und hat große Ohren.
Elefant ist Groß und hat riesen Ohren.
Es gibt unterschiedliche Hunde, ein Hund ist laut.
Eine Maus hat viele Freunde.
...
...
...
Nun möchte ich die Satz.txt Zeile für Zeile nach den Wörtern aus der Liste.txt durchsuchen und es darf das Wort "Freunde" nicht vorkommen und den gefundenen Satz verändern und in eine neuerSatz.txt Datei schreiben.

Mein bisheriger Versuch...

Code: Alles auswählen

with ("Satz.txt",'r') as file:
	liner = file.readlines()
i = 0
while i < len(liner):
        keyword = linecache.getline("Liste.txt", i)
        nicht_da = "Freunde"
        with open("Satz.txt",'r') as inF:
            for line in inF:
                    if keyword in line:
                                if not nicht_da in line:
                                        with open("neuerSatz.txt","w") as file:
                                        	file.write("Old_Line:" + "\n")
                                        	file.write(line)
                                        	neuerSatz = line.replace("ist","kann')
                                        	file.write("New_Line:" + "\n")
                                        	file.write(neuerSatz)
                                        	with open("Satz.txt",'r') as satz:
                                        		Old_liner = linecache.getline("temp.file", 2)
                                            	new_liner = linecache.getline("temp.file", 4)
                                            	with open("Satz.txt",'r') as sat:
                                            		Listelesen = sat.read()
                                            		Listeneu = Listelesen.replace(Old_liner,new_liner)
                                            		with open("Liste.txt",'w') as lol:
                                            			lol.write(Listeneu)
Irgendwie wird nichts in die temp.file geschrieben. Und bekomme auch keine Fehlermeldung vom Log.

Hat jemand eine Idee wie ich das anders machen kann?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Mir wird da zu oft `Satz.txt` gelesen und dann wieder gelesen und dann wird da noch etwas mit linecache gemacht...
Um ein gut zu verstehendes Programm zu schreiben, ist es wichtig, dass man Funktionen hat, die genau eine Sache machen, und nicht verschiedene Sachen gemischt.
Daher, trenne das Lesen oder Schreiben in irgendwelche Dateien vom Verarbeiten der Daten.
Erster Schritt wäre es also, alles was Du brauchst in passende Datenstrukturen zu lesen. So wie ich das jetzt sehe, sind das Listen.
Dann schreibst Du eine Funktion, die aus der Satz-Liste für eine Keyword eine neue, angepasste Liste erzeugt.
Diese Funktion kannst du dann in einer Schleife für alle Keywords aufrufen.
Zum Schluß willst Du wahrscheinlich die Ergebnisliste wieder in eine Datei schreiben.

Teste jede Funktion ausführlich, dass sie auch das macht, was Du möchtest.

Zum Code allgemein: Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 4 mal 8, mal 12.
Variablennamen sollten psrechend sein. Listelesen oder Listeneu sagen nichts darüber aus, für was die Liste da ist. lol oder sat sind komplett nichtssagend. Was ein Liner ist, egal ob alt oder neu, weiß auch keiner, bis auf Dich vielleicht.
Nach Konvention werden Variablennamen klein_mit_unterstrich geschrieben.
LRK
User
Beiträge: 38
Registriert: Sonntag 16. Juni 2019, 21:00

Aber danke,
Ich möchte die Wörter aus der einen Liste in der anderen Liste suchen und mir den Zeilen-Text zurück geben lassen um ihn zu verändern.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Ja, und dieses „möchte” mußt Du in eine Form übersetzen, dass es auch ein Computer versteht.
Wenn Du bei einem der Punkte, die ich genannt habe, nicht weiter kommst, dann zeige hier einfach den Code, den Du versucht hast, und welchen Fehler es gibt, dann wird Dir bestimmt weiter geholfen.
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@LRK: Vielleicht mal als Anregung wie man so ein Problem in kleinere Teilprobleme zerlegen und die dann mit kleinen Funktionen lösen kann, und wie man bei der Entwicklung vorgehen kann. Damit es keine Lösung ist, die man einfach so kopieren kann, weil das sehr nach Hausaufgaben aussieht, verwende ich die Programmiersprache Hy. Das ist ein Lisp-Dialekt der in Python implementiert ist, und auch alle Module und Packages verwenden kann, die das Python mit dem man das Hy-Programm ausführt, verwenden kann.

Als erstes muss man sich die Eingabedaten und das Ergebnis klar machen. Eingaben gibt es zwei: Die Datei mit den Worten und die Datei mit den Sätzen. Die mit den Sätzen soll Zeile für Zeile in eine neue Datei transformiert werden, wobei auch Sätze herausgefiltert werden sollen.

Da man immer nur einen Satz zur gleichen Zeit betrachten muss, und jeden nur ein einziges mal, sind die Sätze der Teil der Eingabe die nicht gleich am Anfang komplett in den Speicher geladen werden muss. Die Worte braucht man dagegen bei der Entscheidung ob eine Zeile behalten werden soll, also für jede Zeile erneut, darum sind das Daten die man in den Speicher laden sollte, statt sie immer wieder neu einzulesen.

Programmentwicklung passiert in der Regel Schritt für Schritt, wobei man mit jedem Schritt versucht dem Ergebnis näher zu kommen und jeden Schritt testet.

Der erste Schritt ist das einlesen der Daten. Dafür könnte man sich eine Funktion schreiben die einen Generator über die Zeilen einer Datei liefert, deren Dateinamen man der Funktion übergibt. Im Hauptprogramm kann man zum Testen dann erst einmal die Zeilen in einer Liste sammeln und mit `print` ausgeben. Am Anfang noch ein paar Konstanten definiert für die Dateinamen und die Kodierung der Textdateien, könnte das so aussehen:

Code: Alles auswählen

#!/usr/bin/env hy3
(import [contextlib [closing]])

(setv *sentences-filename* "Satz.txt"
      *words-filename* "Liste.txt"
      *result-filename* "SatzNeu.txt"
      *encoding* "UTF-8")


(defn create-line-generator [filename]
  (with [lines (open filename "r" :encoding *encoding*)]
    (yield-from lines)))


(defmain [&rest args]
  (with [sentences (closing (create-line-generator *sentences-filename*))]
    (->> (list sentences)
         (print))))
Als nächstes müssen wir die ungewünschten Sätze rausfiltern. Fangen wir mit denen an die "Freunde" enthalten. Dafür kann man sich eine Funktion schreiben die testet ob dieses Kriterium erfüllt ist, und das dann mit `remove` auf die Sätze anwenden:

Code: Alles auswählen

(defn contains-friends? [sentence]
  (in "Freunde" sentence))


(defmain [&rest args]
  (with [sentences (closing (create-line-generator *sentences-filename*))]
    (->> (remove contains-friends? sentences)
         ((comp print list)))))
Und schon hat man die Sätze mit "Freunde" nicht mehr im Ergebnis.

Als nächstes ein Positiv-Filter, nämlich nur noch Sätze ins Ergebnis durchlassen, die mindestens ein Wort aus ``Liste.txt`` enthalten. Dazu müssen wir die Worte erst einmal einlesen. Das erledigt eine Funktion die alle Zeilen in eine Liste einliest und dabei die Zeilenendezeichen entfernt:

Code: Alles auswählen

(defn load-words [filename]
  (with [lines (closing (create-line-generator filename))]
    (lfor line lines (.rstrip line))))
Wenn man die Worte hat, kann man eine Funktion schreiben, die testet ob mindestens eines der Worte im Satz vorkommt:

Code: Alles auswählen

(defn contains-any-of? [words sentence]
  (any (map (fn [word] (in word sentence)) words)))
Und die beiden Funktionen in die Hauptfunktion integriert sorgt dafür, dass nur noch die gewünschten Sätze im Ergebnis sind:

Code: Alles auswählen

(defmain [&rest args]
  (with [sentences (closing (create-line-generator *sentences-filename*))]
    (->> (remove contains-friends? sentences)
         (filter (partial contains-any-of? (load-words *words-filename*)))
         ((comp print list)))))
Jetzt können die übriggebliebenen Sätze verändert werden. Dazu wieder eine kleine Funktion die einen Satz verändert:

Code: Alles auswählen

(defn modify-sentence [sentence]
  (.replace sentence "ist" "kann"))
Die kann man jetzt im Hauptprogramm auf jeden übriggebliebenen Satz anwenden:

Code: Alles auswählen

(defmain [&rest args]
  (with [sentences (closing (create-line-generator *sentences-filename*))]
    (->> (remove contains-friends? sentences)
         (filter (partial contains-any-of? (load-words *words-filename*)))
         (map modify-sentence)
         ((comp print list)))))
Bleibt zum Schluss nur noch das wegschreiben in eine Datei. Wie gehabt, mit einer kleinen Funktion die das sammeln in einer Liste und das Ausgeben per `print` im Hauptprogramm ersetzt:

Code: Alles auswählen

(defn save-sentences [filename sentences]
  (with [file (open filename "w" :encoding *encoding*)]
    (.writelines file sentences)))
Führt zu folgendem Gesamtprogramm:

Code: Alles auswählen

#!/usr/bin/env hy3
(import [contextlib [closing]]
        [functools [partial]])

(setv *sentences-filename* "Satz.txt"
      *words-filename* "Liste.txt"
      *result-filename* "SatzNeu.txt"
      *encoding* "UTF-8")


(defn create-line-generator [filename]
  (with [lines (open filename "r" :encoding *encoding*)]
    (yield-from lines)))


(defn contains-friends? [sentence]
  (in "Freunde" sentence))


(defn load-words [filename]
  (with [lines (closing (create-line-generator filename))]
    (lfor line lines (.rstrip line))))


(defn contains-any-of? [words sentence]
  (any (map (fn [word] (in word sentence)) words)))


(defn modify-sentence [sentence]
  (.replace sentence "ist" "kann"))


(defn save-sentences [filename sentences]
  (with [file (open filename "w" :encoding *encoding*)]
    (.writelines file sentences)))


(defmain [&rest args]
  (with [sentences (closing (create-line-generator *sentences-filename*))]
    (->> (remove contains-friends? sentences)
         (filter (partial contains-any-of? (load-words *words-filename*)))
         (map modify-sentence)
         (save-sentences *result-filename*))))
In Python kann man bei der Entwicklung grundsätzlich genau so vorgehen. Da Hy recht nah dran ist an Python, würde das Programm sogar sehr ähnlich aussehen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten