Wörter mit gleichem Anfangsbuchstaben

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
Androschka888
User
Beiträge: 1
Registriert: Freitag 26. November 2021, 09:55

Hi, ich muss aus einer Textdatei alle Wörter herausfinden, die mit dem gleichen Anfangsbuchstaben beginnen. Dazu habe ich diesen Code geschrieben:
relative_path = 'filename.txt'
def get_last_letter_as_first(letter, all_strings):
with open( relative_path, 'r') as text_file:
all_strings = text_file.read().split('\n')

for letter in len(all_strings):
if letter == all_strings[0]
return string

get_string_list_for_letter(letter, all_strings)

Und jetzt weiß ich irgendwie nicht ob es richtig ist , bzw was daran falsch ist.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Alles, was eine Methode braucht, muß sie über ihre Argumente bekommen. Warum ist es wichtig, dass es sich bei dem Dateinamen um einen relativen Pfad handelt. Warum dürfen das keine absoluten Pfade sein?
Beim Öffnen einer Text-Datei muß man immer das richtige Encoding angeben.
Wenn man alle Zeilen in einer Liste haben möchte, dann benutzt man nicht split.

Dann hast Du einige Syntaxfehler: fehlende :, falsch Einrückung.
Was daran falsch ist, sollte Dir die Fehlermeldung sagen, die Du bekommst.
Dann mußt Du Dir überlegen, über was die Schleife laufen soll. Aus Deinem Code und Deiner Beschreibung bin ich mir nicht sicher, was Du eigentlich willst.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Zusätzlich: Wenn du hier im Forum Code postest, solltest du den zwischen Code-Tags schreiben. Die Tags werden automatisch eingefügt, wenn du den </>-Button im vollständigen Editor drückst. Dann bleibt die Einrückung erhalten - und die ist in Python nun einmal wichtig.
P_Python
User
Beiträge: 19
Registriert: Donnerstag 11. November 2021, 19:45

Das könnte man z.B. so machen:

Code: Alles auswählen

LETTER = "A","a"

def word_filter(words,letter_list):
    for count, word in enumerate(words):
        if word[0] in LETTER:
            if not str.isalpha(word[-1]):
                #Satzzeichen entfernen
                words[count]=(word.replace(word[-1],""))
            letter_list.append(words[count])


    
letter_list = []
with open("text.txt","r",encoding ="utf-8") as file:
    for zeile in file:
        words = zeile.split()
        word_filter(words,letter_list)
print(letter_list)
        

Gibts noch eine elegantere Möglichkeit?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@P_Python: Das ist eine sehr komische Aufteilung von Code der in der Funktion ist und dem der nicht dort ist. Wenn eine Funktion eine übergebene Liste ändert, sollte das Beispielsweise am Namen erkennbar sein oder deutlich dokumentiert sein. Besser wäre es wenn die Funktion das gar nicht machen würde, sondern einfach eine neue Liste mit den gefilterten Worten zurückgeben würde. Und was ich hier überhaupt nicht verstehe, ist warum die übergebene `words`-Liste verändert wird‽

`LETTER` (Einzahl) ist kein guter Name für ein Tupel mit Buchstaben (Mehrzahl). Auch wenn das ja eigentlich nur ein Buchstabe ist. Das kann man sich aber auch sparen in dem man den Anfangsbuchstaben entweder in einen Gross- oder Kleinbuchstaben wandelt, und dann den mit *einem* 'a' oder 'A' vergleicht; je nach dem ob man die kanonische Form lieber gross oder klein haben möchte.

Methoden ruft man auf dem Objekt auf, nicht auf der Klasse mit dem Objekt als Argument.

Das mit dem `replace()` ist keine gute Idee, denn man muss sich dann ziemlich sicher sein, dass der nicht-buchstabe nicht auch *im* Wort selber noch einmal vorkommen kann. Und es ist semantisch ja auch nicht das was man da ausdrücken will: Überall ersetzen ist halt was anderes als nur am Ende ersetzen. Und der Kommentar sagt Satzzeichen, was aber nirgends geprüft wird. Denn ersetzt werden nicht nur Satzzeichen, sondern beispielsweise auch Ziffern, Bindestriche, und auch alles andere was kein Buchstabe ist.

Grunddatentypen haben nichts in Namen zu suchen, denn den Datentyp ändert man öfter mal im Laufe der Programmentwicklung, und dann hat man entweder falsche, irreführende Namen im Quelltext stehen, oder man muss überall die Namen anpassen. Hier würde man Beispielsweise eher eine Menge verwenden, denn in einer Liste wären mehrfach vorkommende Worte ja alle enthalten, was IMHO nicht wirklich Sinn macht. `letter_list` ist auch inhaltlich komisch, denn da würde man eine Liste mit Buchstaben erwarten.

Warum `zeile` wenn die aus `file` kommt und in `words` aufgeteilt wird. Also warum nicht `line` aus `datei`, aufgeteilt in `worte`? Oder eine der anderen insgesamt 8 Möglichkeiten diese drei Namen entweder Englisch oder Deutsch zu benennen?

Code: Alles auswählen

#!/usr/bin/env python3
from itertools import chain

LETTER = "a"
assert LETTER.casefold() == LETTER


def remove_non_alpha_suffix(word):
    while word and not word[-1].isalpha():
        word = word[:-1]
    return word


def main():
    with open("test.txt", "r", encoding="utf-8") as file:
        words = chain.from_iterable(line.split() for line in file)
        result = set(
            remove_non_alpha_suffix(word)
            for word in words
            if word[0].casefold() == LETTER
        )
    print(sorted(result, key=lambda word: word.casefold()))


if __name__ == "__main__":
    main()
Das entfernen von nicht-Buchstaben vom Wortende ist nicht schön und/oder effizient gelöst und IHMO auch an der falschen Stelle, denn `words` stimmt dann ja nicht so wirklich als Name. Das würde ich wohl eher beim zerlegen in Worte schon entfernen und dort etwas weniger simpel. Also mindestens mit einem regulären Ausdruck, oder aber mit schwereren Geschützen wie NLTK & Co.

@Androschka888: Wie ist denn die Textdatei überhaupt aufgebaut? Ist das wirklich ein Text wo die Zeilen in zu untersuchende Worte aufgeteilt werden müssen, oder ist das ein Wort pro Zeile?

Und Du solltest vielleicht auch mal genau sagen was gemacht werden soll, also wie das Ergebnis aussehen soll. Sollen beispielsweise alle Worte nach Anfangsbuchstaben gruppiert werden, oder soll *ein* Buchstabe vorgegeben werden, zu dem dann alle Worte herausgefiltert werden, oder etwas völlig anderes? Da ist die Beschreibung in der Frage nicht präzise genug.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten