Seite 1 von 1

dictionary key ausgeben

Verfasst: Donnerstag 6. April 2023, 23:40
von norgsmen
Hi Leute,

es geht um diesen Code hier:

Code: Alles auswählen

fobj = open('bsp.txt', 'r')

wo_dict = {}
for line in fobj:
    line = line.strip()
    zuordnung = line.split(' ')
    wo_dict[zuordnung[0]] = zuordnung[1]

nutzerfrage = input()

if nutzerfrage in wo_dict:
    print(wo_dict[nutzerfrage])
else:
    for key, value in wo_dict.items():
        print(wo_dict[key])
und zwar habe ich eine Textdatei mit:

Deutschland Germany
Fankreich France
Spanien Spain


erstellt. Nun will ich das Programm so erweitern, dass, falls die nutzerfrage den value des dictionarys entspricht, dass dann demnach der key ausgegeben werden soll (der deutsche Begriff) Hat jemand dazu eine Idee?

Danke fürs Antworten:D

Re: dictionary key ausgeben

Verfasst: Freitag 7. April 2023, 05:13
von __blackjack__
@norgsmen: Was willst Du denn da erweitern? Das was Du beschreibst, leistet das Programm doch schon‽

Anmerkungen zum Quelltext: Namen sollten keine kryptischen Abkürzungen enthalten. Der Zweck von Namen ist es dem Leser klar zu vermitteln wofür der Wert dahinter im Programm steht. Namen wie `fobj` und `wo_dict` tun das nicht. Beim `fobj` macht das `obj` nicht wirklich Sinn, denn *alles* was man an einen Namen binden kann, ist in Python ein Objekt.

Grunddatentypen wie `dict` haben in Namen auch nichts zu suchen. Während der Entwicklung kann es vorkommen, dass man einen Datentyp durch einen anderen, spezialisierteren ersetzt, und dann hat man entweder falsche, irreführende Namen im Quelltext, oder muss alle betroffenen Namen suchen und anpassen.

`key` und `value` sind zwar Namen die nicht abgekürzt sind und auch keine Grunddatentypen enthalten, aber sie sind sehr allgemein gehalten. Da sollte man bessere Namen verwenden, welche die Bedeutung der Werte enthalten. Wie `german_country_name` und `english_country_name`.

Wörterbüchern werden oft Namen nach dem Muster `key_to_value` benannt, wobei für `key` etwas gewählt wird das einen einzelnen Schlüssel beschreibt, und für `value` etwas das einen einzelnen Wert beschreibt.

Man sollte nicht verschiedene Sprachen für Namen verwenden, denn sonst muss man immer überlegen ob man einen Deutschen oder einen Englischen Bezeichner verwendet hat.

Man muss auch nicht jedes Zwischenergebnis an einen Namen binden.

Beim öffnen von Textdateien sollte man immer explizit die Kodierung angeben. Denn bei Ländern mit Zeichen ausserhalb von ASCII-Zeichen, z.B. Österreich muss man dem Programm mitteilen, wie die kodiert sind, und sich nicht auf die Kodierung verlassen, die Python ”rät”, und die auf unterschiedlichen Systemen anders sein kann.

Dateien die man öffnet, sollte man auch wieder schliessen. Am besten verwendet man wo es geht die ``with``-Anweisung dafür.

Statt undurchsichtiger Indexzugriffe sollte man die beiden Teile der am Leerzeichen getrennten Zeile gleich an sinnvolle Namen binden.

Wobei das mit den Leerzeichen ein Problem ist, denn es gibt sowohl im Deutschen als auch im Englischen Ländernamen mit Leerzeichen. Siehe Kommetar im Quelltext weiter unten.

Die ``for``-Schleife bei der Ausgabe verwendet `value` gar nicht, dafür `key` nur im den `value` dazu zu ermitteln, den man durch die ``for``-Schleife ja bereits hätte, womit `key` das ist, was eigentlich gar nicht benötigt wird. Man könnte da einfach direkt nur über die Werte iterieren.

Hier der überarbeitete Quelltext (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3


def main():
    with open("bsp.txt", encoding="ascii") as lines:
        german_to_english_country_name = {}
        for line in lines:
            #
            # BUG This doesn't work with country names, german or english,
            # containing spaces.  For instance Costa Rica, Burkina Faso, Puerto
            # Rico and so on.
            #
            german_name, english_name = line.strip().split(" ")
            german_to_english_country_name[german_name] = english_name

    german_name = input()
    if german_name in german_to_english_country_name:
        print(german_to_english_country_name[german_name])
    else:
        for english_name in german_to_english_country_name.values():
            print(english_name)


if __name__ == "__main__":
    main()

Re: dictionary key ausgeben

Verfasst: Freitag 7. April 2023, 07:58
von norgsmen
@__blackjack__ Hi, danke für die ganzen Tipps. Also wenn ich als nutzerfrage 'Deutschland' eingeben, dann wird so wie ich es erwarte 'Germany' ausgegeben.
Aber ich will, dass das auch anderes herum funktioniert. Und zwar, wenn ich 'Germany' angebe, dann soll nur 'Deutschland' ausgegeben werden. Bei mir kommt das hier:

Germany
Germany
France
Spain

Re: dictionary key ausgeben

Verfasst: Freitag 7. April 2023, 09:04
von snafu
Dann kehre das Wörterbuch halt um:

Code: Alles auswählen

english_to_german = {english: german for german, english in german_to_english.item()}

Re: dictionary key ausgeben

Verfasst: Freitag 7. April 2023, 09:57
von norgsmen
@snafu Es hat geklappt! Dankeschön:)

Re: dictionary key ausgeben

Verfasst: Freitag 7. April 2023, 10:22
von DeaD_EyE
Hier mal ein ähnlicher Ansatz mit mehr Code:

Code: Alles auswählen

END = "\n" * 2


def load_data(textfile):
    with open(textfile) as fd:
        ger2eng = {row[0]: row[1] for line in fd if (row := line.strip().split())}

    eng2ger = {value: key for key, value in ger2eng.items()}
    return ger2eng, eng2ger


def nutzerfrage(ger, eng):
    """
    - Leerzeichen werden links und rechts vom string abgeschnitten
    - Anfangsbuchstaben der Wörter groß schreiben (title())
    - dann die Englische oder Deutsche übersetzung zurückliefern
    - wenn beide nicht zutreffen, liefert die get-methode ein None zurück
    """
    user_input = input().strip().title()
    return ger.get(user_input) or eng.get(user_input), user_input


def main():
    """
    Hauptfunktion mit Endlossschleife
    """
    ger_mapping, eng_mapping = load_data("bsp.txt")
    print("STRG+C zum beenden", end=END * 2)

    while True:
        antwort, benutzer_eingabe = nutzerfrage(ger_mapping, eng_mapping)
        if antwort is None:
            print(f"Wort {benutzer_eingabe} nicht gefunden", end=END)
        else:
            print(f"Übersetzung: {antwort}", end=END)


if __name__ == "__main__":
    # wird nur ausgeführt, wenn das Programm mit Python gestartet wird
    # wird nicht ausgeführt, wenn dieses Modul durch Python importiert wird
    # KeyboardInterrupt abfangen, um das Programm mit STRG+C beenden zu können
    # und um einen Text auszugeben. \r springt zum Anfang der Zeile zurück.
    # Wenn man STRG+C betätigt, erscheint in der Konsole die Zeichenfolge ^C.
    try:
        main()
    except KeyboardInterrupt:
        print("\rProgramm beendet.")