Seite 1 von 2

merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 21:09
von Eliazz
Hallo,
eine Kurze Erklärung:
Mein Vater ist Heilpraktiker und ich habe mir überlegt ob ich nicht eine Software schreiben könnte, die ihm die Arbeit abnimmt bzw erleichtert, und zwar folgendermaßen: Es gibt Syntome und zu jedem Syntom eine Liste wirkungsvoller Heilmittel. Einen ganz kleinen Ausschnitt zu Testzwecken habe ich erstellt, er ist nicht wahrheitsgetreu und dient wie gesagt ausschließlich zu Testzwecken. Der User kann jetzt eingeben, was er für Syntome miteinander abgleichen möchte und soll jetzt das Heilmittel ausgespukt bekommen, das unter allen Syntomen zu finden ist. Eigentlich nicht so schwer. Aber ich habe ein Problem das mich irgendwie stutzig gemacht hat. Hier ersteinmal der Quellcode:

Code: Alles auswählen


verzeichnis = {
    'Abmagerung' : [ 'ares' , 'merc' , 'lyc' , 'nat-m' ]  ,
    'Asthma' : [ 'ars' , 'nat-m' , 'lyc' , 'phos' ] ,
    'Kälte' : [ 'ars' , 'merc'  , 'sil' , 'lyc' , ]
    }


run = True
syn_list = []
sy_count = 0

while run == True:
    syntom = input ('Gib ein Synthome ein: ')
    if syntom is '0' or  syntom is '-' or syntom is '/' or syntom is 'q':
        run = False
    else:
        syn_list.append(syntom)
        sy_count += 1

vergleich_len = 0
vergleich_save = ''
for längstes in range (0, len(syn_list)):
    if len(verzeichnis[syn_list[längstes]]) > vergleich_len:
        vergleich_save = syn_list[längstes]
        vergleich_len = len(verzeichnis[syn_list[längstes]])

vergleich_list = verzeichnis[vergleich_save]
counter = 0
cop_vergleich_list = vergleich_list
print(cop_vergleich_list) # Überprüfung
for main in cop_vergleich_list:
    print(main) # Meine große frage ist hier zu finden
    r_counter = 0
    for u_main in verzeichnis:
        if main in verzeichnis[u_main]:
            r_counter += 1
    if r_counter != sy_count:
        del vergleich_list[counter]
    counter = counter + 1
print(vergleich_list) 
    
Auf das Programm selber muss eigentlich nicht weiter eingegangen werden (okay wenn ihr Ideen, Anregung und Kritik habt gerne)
Meine Frage ist nur: warum wird in der --> for main in cop_vergleich_list beim zweiten Durchlauf das 2te Element von cop_vergleich_list übersprungen?????? Um zu sehen was ich meine gebt im Input bitte

1. Abmagerung
2. Asthma
3. Kälte
4. q

ein.

Die Liste die zuerst ausgegeben wird ist: ['ares', 'merc', 'lyc', 'nat-m']
das ist die Ausgangsliste. Jetzt setze ich eine "for in - Schleife" auf diese Liste an, was im ersten Durchlauf funktionier, im 2ten allerdings 'merc' überspringt. Wenn ich die letzten 4 Code Zeilen (39-43) "out commente", sprich weglasse klappt es, aber ich weiß nicht wo da der Fehler ist...

if r_counter != sy_count:
del vergleich_list[counter]

Hierbei verändere ich ja nichtmal irgendetwas an der an die for schleife geknüpfte Liste, also warum wird 'merc' hier übersprungen?


Ja ich weiß es ist sehr speziell, aber ich hoffe jemand kann mir helfen.
MFG

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 21:17
von Eliazz
Ich habe das Problem jetzt umgagnen in dem Ich statt aus einer vollen Liste alle "falschen" zu löschen in eine neue alle "richtigen" eintrage, aber es interessiert mich trotzdem total, denn die alte Version müsste IMO auch funktionieren, tut sie aber nicht :(

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 21:30
von BlackJack
@Eliazz: Du löschst Elemente aus einer Liste über die Du gerade iterierst. Damit rücken allen folgenden Elemente einen Index nach vorne und die ``for``-Schleife überspringt dann scheinbar Elemente. Weil die an einen Index in der Liste gerückt sind, der von der Schleife bereits betrachtet wurde. Fazit: *Sehr* vorsichtig sein wenn man Objekte verändert über die man gerade gleichzeitig iteriert.

Letztlich solltest Du sowieso nichts aus Listen mit ``del`` löschen. Das kann sinnvoll sein, ist es aber nur in ganz seltenen Fällen. In aller Regel erstellt man eine neue Liste die nur die Elemente enthält die man haben möchte.

In Deinem Fall sind Listen aber die falsche Datenstruktur. Was Du da machst, die Schnittmenge berechnen ist eine Mengenoperation und dafür hat Python einen eigenen Datentyp: `set`.

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 21:34
von EyDu
Du gehst das Problem von der ganz falschen Seite an (ok, das eigentliche Problem ist, dass Heilpraktiker überhaupt ein zugelassener Beruf ist), du möchtest eigentlich mit Mengen arbeiten. Damit lässt sich dein Problem ganz einfach lösen. In diesem Fall musst du nur die Schnittmenge aller "Medikamente" zu allen auftretenden Symptomen bilden. Dann hast du das Ergebnis.

Dann noch ein paar Anmerkungen zum Code:

Ein Vergelich der Art ``x == True`` ist immer sinnlos. Wenn x wahr ist, dann kommt als Ergebnis nur wieder True raus. Wenn x nicht wahr ist, dann kommt False raus. Das streckt aber bereits in x drin, also kannst du dir den Vergleich gleich sparen. Bei Vergleiche auf ``x == False`` ist der Fall analog. Dort verwendest du ``not x``.

Statt der run-Variable solltest du besser ``while True:`` verwenden und stat ``run = False`` die Schleife mit break verlassen. Das ist in diesem Fall deutlich übersichtlicher.

``is`` vergleich nicht auf Gleichheit, ``is`` vergleicht auf Identität. Das sind zwei Verschiedene Dinge. In diesem Fall möchtest du alle drei Vergeliche mit ``==`` machen. Eigentlich willst du aber noch kürzer teste:

Code: Alles auswählen

if symptom in ("0", "-", "/", "q")
``sy_count`` ist überflüssig, die gleiche Information steckt in ``len(syn_list)``. Dabei kannst du gleich mal an deiner Namensgebung arbeiten. Warum kürzt du die Namen unnötig ab? Du legst es wohl darauf an, dass du dein Programm in drei Wochen nicht mehr lesen kannst ;-) Benutze besser aussagekräftige Bezeichner.

Außedem solltest du Datentypen aus den Namen rauslasen. ``symptome`` ist ein viel besserer Name als ``syn_list``. Hinzu kommt das Problem, falls du den Datentyp mal ändern solltest, dann müsstest du den Namen überall in deinem Proramm anpassen. In diesem Fall wäre das sogar notwendig, da die Symptome eigentlich gar keine Liste sind, sondern eine Menge.

Wenn du das Muster ``fox i in range(len(...))`` verwendest, dann machst du in der Regel etwas verkehrt. In Python kannst du direkt über Elemente in Containern iterieren und solltest das auch tun. Wenn du einen Index brauchst, dann ziehe die enumerate-Funktion hinzu. In deinem Fall macht es sogar noch Probleme, wenn du die Liste der Symptome auf eine Menge umstellst, dann bricht dein Programm (völlig unnötig) mit einem Fehler ab.

Wenn keine Symptome eingegeben werden, dann wird dein Programm abstürzen, da ``vergleich_save`` und ``vergleich_len`` nicht bekannt sind. Auch die beiden Dinger sind wieder unnötig, warum speicherst du die Information nicht direkt? Und noch viel besser ginge das mit der max-Funktion, dann kannst du dir diese unelegante Schleife sparen. Auch sind die beiden Namen wieder extrem schlecht gewählt.

Die Zuweisung ``cop_vergleich_list = vergleich_list`` ist sinnfrei, damit kopierst du die Liste nur an einen Namen und nicht an eine Kopie. Daher rührt auch dein Fehler. In Python werden niemals implizit Kopien erzeugt, dass musst du immer explizit machen. In diesem Fall mittels ``vergleich_list[:]``. Daher kommt auch dein Fehler. Du arbeitest immer auf der selben Liste. Einfachste Lösung: Arbeite nicht auf Listen rum, erstelle einfach eine neue. Das ist übersichtlicher und geht schneller.

Generell solltest du an deiner Namensgebung arbeiten und aussagekräftige Bezeichner verwenden. Dein Programm ist vollkommen unverständlich. Von Vorteil wäre es auch, wenn du dich mit dir auf eine Sprache einigen könntest. Entweder Englisch oder Deutsch. Ein Mix aus beidem ist sehr ekelhaft zu lesen.

Auch solltest du die ganze Funktionalität in einezelnen Funktionen kapseln, dann wird die ganze Sache ein wenig übersichtlicher und leichter testbar. Zu gutzer letzt fehlt auch noch eine main-Funktion, in der dein Programm gekapselt ist:

Code: Alles auswählen

def main():
    HIER DEIN PROGRAMM

if __name__ == "__main__":
    main()
Dann kannst du dein Programm auch importieren, ohne dass es sofort ausgeführt wird.

Da sind an jeder Ecke noch viele Kleinigkeiten die verbessert werden sollten, mit den Hinweisen hast du jetzt aber erstmal genug zu tun.

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 21:36
von Eliazz
@ Blackjack: Das ist ja das Problem, eben nicht! Ich habe extra eine Kopie erstellt und was in der Schleife passiert, hat absolut nichts mit der cop_vergleich_list zu tun... im Schleifen Körper wird cop_vergleich_list ja gar nicht genannt, was überseh ich da?

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 21:43
von Eliazz
EyDu!
Danke für deinen Beitrag, könntest du mir einen Tutorial Link zu der Sache mit den Mengen schicken, das Beigreif ich noch nicht ganz, alles andere finde ich plausibel... Sorry bin erst 14 und noch recht neu mit Python. If tutorial_content_language == english:
print('Englisch ist kein Problem)

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 22:24
von BlackJack
@Eliazz: Eine einfache Zuweisung erstellt keine Kopie. Wenn Du ``a = b`` schreibst, dann hast Du ein und das selbe Objekt was vorher an `b` gebunden war, *auch* an den Namen `a` gebunden. (Jetzt habe ich endlich verstanden was der Polizist in `cop_vergleich_list` zu suchen hatte. :-))

Weitere Anmerkungen zum Quelltext:

Der Spellchecker sagt es heisst „Symptom”. :-)

`verzeichnis` ist ein sehr allgemeiner Name der nichts darüber sagt was die Daten in der Datenstruktur *bedeuten*. Bei Wörterbüchern sieht man oft Namen nach dem Muster `schluessel2wert` (oder `SCHLUESSEL_TO_WERT` bei Konstanten) wobei die beiden Teile vor und nach `2` beziehungsweise `_TO_` die Bedeutung von Schlüssel und Wert beschreiben sollten.

Namen sollten weder Abkürzungen enthalten die nicht allgemein bekannt sind, weil der Leser dann im Zweifelsfall mehr mit rätseln als mit verstehen des Quelltextes beschäftigt ist („cop”?), noch den konkreten Datentyp des Wertes. Wenn man den Typ nämlich irgendwann einmal ändert dann muss man den Namen überall anpassen was Arbeit macht und fehleranfällig sein kann, oder man hat irreführende Namen im Programm. `syn_list` würde zum Beispiel besser `symptoms` heissen. Und `sy_counter` besser `symptom_count`. Wobei man das eigentlich gar nicht braucht, denn damit hast Du zwei redundante Daten wo Du aufpassen musst, dass die immer synchron bleiben. Das ist aber unnötig, weil man die Anzahl ja jederzeit mit `len()` von der Liste abfragen kann. Das ist eine Fehlerquelle weniger.

Was Du nach der Eingabe mit den ganze Zählern und Schleifen anstellst ist mir jetzt zu mühselig nachzuvollziehen. Das ist total unübersichtlich. Nur eins noch: Code nach dem Muster ``for i in range(len(sequence)):`` nur um dann mit dem Index auf einzelne Elemente von `sequence` zuzugreifen ist in Python ein „anti pattern”. Man kann in Python *direkt* über die Elemente iterieren, ohne eine zusätzliche Indirektion über einen Index:

Code: Alles auswählen

    # 
    # anstatt:
    # 
    vergleich_len = 0
    vergleich_save = ''
    for laengstes in range(0, len(symptoms)):
        if len(SYMPTOM_TO_PLACEBOS[symptoms[laengstes]]) > vergleich_len:
            vergleich_save = symptoms[laengstes]
            vergleich_len = len(SYMPTOM_TO_PLACEBOS[symptoms[laengstes]])
    # 
    # besser:
    # 
    vergleich_len = 0
    vergleich_save = ''
    for symptom in symptoms:
        if len(SYMPTOM_TO_PLACEBOS[symptom]) > vergleich_len:
            vergleich_save = symptom
            vergleich_len = len(SYMPTOM_TO_PLACEBOS[symptom])
Wobei hier im Original der Name `laengstes` für mich überhaupt keinen Sinn ergeben hat.

Vielleicht an der Stelle doch mal ein Beispiel warum ich mich in diesen Code eigentlich gar nicht reindenken möchte. Denn was Du da so umständlich formulierst scheint einfach nur das ermitteln der längsten Liste aus dem Wörterbuch zu sein. Das ist ein Einzeiler:

Code: Alles auswählen

    vergleich_list = max(SYMPTOM_TO_PLACEBOS.values(), key=len)
Wenn man das deutlich komplizierter schreibt, sollte man zumindest einen Kommentar drüber setzen was der Code da eigentlich tut, oder es in eine entsprechend benannte Funktion auslagern.

Wenn man den richtigen Datentyp und hilfreiche Funktionen aus der Standardbibliothek verwendet kann das ganze so aussehen:

Code: Alles auswählen

from functools import reduce
from operator import and_

SYMPTOM_TO_PLACEBOS = {
    'Abmagerung': ['ares', 'merc', 'lyc', 'nat-m'],
    'Asthma': ['ars', 'nat-m', 'lyc', 'phos'],
    'Kälte': ['ars', 'merc', 'sil', 'lyc'],
}


def main():
    symptoms = list()
    while True:
        symptom = input('Gib ein Symptom ein: ')
        if symptom in ['0', '-', '/', 'q']:
            break
        else:
            symptoms.append(symptom)

    common_placebos = reduce(
        and_, (set(SYMPTOM_TO_PLACEBOS[s]) for s in symptoms)
    )
    print(common_placebos)


if __name__ == '__main__':
    main()

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 22:44
von EyDu
BlackJack hat geschrieben:

Code: Alles auswählen

SYMPTOM_TO_PLACEBOS
:mrgreen:

Re: merkwürdige for - Schleife

Verfasst: Montag 7. Oktober 2013, 22:55
von EyDu
Eliazz hat geschrieben:Danke für deinen Beitrag, könntest du mir einen Tutorial Link zu der Sache mit den Mengen schicken, das Beigreif ich noch nicht ganz, alles andere finde ich plausibel...
Hier ist der Abschnitt aus der Python-Dokumentation und bei Wikipedia gibt es natürlich auch etwas zu Mengen. Mit 14 wirst du natürlich kaum die mathematischen Details verstehen (und brauchst du auch gar nicht), aber such einfach mal nach Teilmenge, Schnittmenge und Vereinigung - an den Bildern dazu wird die Bedeutung fast schon klar. Mehr brauchst du im Prinzip nicht zu wissen.

Re: merkwürdige for - Schleife

Verfasst: Dienstag 8. Oktober 2013, 07:33
von Eliazz
Hey danke,
eins muss mir Blackjack aber nochmal genauer erklären: Warum erstellt b = a deiner Meinng nach keine exakte Kopie von a?

Code: Alles auswählen


a = 5
b = a
print(a, type(a))
print(b, type(b))
a = [1,2,'test',2.365]
b = a
print(a, type(a))
print(b, type(b))

Ich bekomme doch beide Male eine exakte Kopie des inhalts, also was ist hier falsch? :O
Bzw. Was ist der Unterschied zu einer "einfachen Zuweisung"?
MFG

Re: merkwürdige for - Schleife

Verfasst: Dienstag 8. Oktober 2013, 08:12
von snafu
@Eliazz: Du zeigst lediglich, dass hinter beiden Namen der gleiche Typ steckt, was auch niemand bestritten hat. Die Situation ist aber so, dass hinter beiden Namen exakt das selbe Objekt steckt und eben keine Kopie. Das ist so, als wenn von 2 verschiedenen Webseiten auf die selbe URL gelinkt wird. Um das zu veranschaulichen:

Code: Alles auswählen

>>> a = [1,2,'test',2.365]
>>> b = a
>>> b.append('foo')  # wirkt sich auch auf `a` aus
>>> a
[1, 2, 'test', 2.365, 'foo']
>>> a is b  # es ist exakt das selbe Objekt
True
>>> b = a[:]  # Kopie wird erstellt
>>> a is b  # jetzt sind es 2 unabhängige Listen mit dem selben Inhalt
False
>>> b.append(123)  # wirkt sich jetzt nur noch auf `b` aus
>>> b
[1, 2, 'test', 2.365, 'foo', 123]
>>> a
[1, 2, 'test', 2.365, 'foo']

Re: merkwürdige for - Schleife

Verfasst: Dienstag 8. Oktober 2013, 08:31
von Eliazz
Achsoooooo,
Jetzt versteh ich alles, was ich bis eben davon nicht verstanden habe und meine grundfrage hast du damit eigentlich auch beantwortet :) danke!! :)

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 08:53
von bfm
Hallo zusammen,

also für mich liest sich die Lösung irgendwie kompliziert.....

Mein Lösungansatz wäre mal so:

eine Tabelle in zB SQLITE mit den Spalten Symptom und Heilmittel. Evtl. noch weitere Tabellen um für die Symptome und Heilmittel noch weitere Daten (zB Dosierung, welches Heilmittel kann mit welchem Heilmittel kombiniert werden, welches geht gar nicht....) zu speichern.
Symthom 1 = Heilmittel A
Symthom 1 = Heilmittel B
Symthom 2 = Heilmittel A
Symthom 2 = Heilmittel C
Symthom 3 = Heilmittel D

So kann man ganz einfach abfragen, welche Heilmittel für ein Symptom geeignet sind. Umgekehrt geht das dann natürlich auch. Welches Heilmittel ist gegen welches Symptom.

In der Regel will man ja aber zu zwei oder mehr Symptomen die übereinstimmenden Heilmittel herausfinden. Hierzu würde ich für jedes Symptom die entsprechenden Heilmittel abfragen und dann vergleichen, welches Heilmittel bei allen Symptomen übereinstimmt. Im Idealfall findet sich ein Heilmittel gegen alle Symptome. Kann aber auch sein, dass es kein Allzweckheilmittel gibt. Ensprechend müsste hier dann das Programm reagieren.
Der Vergleich müsste sich problemlos mit dem Datentyp 'set()' bewerkstelligen lassen. Da gibt es doch glaub sogar schon Methoden, die je nach Bedarf die übereinstimmenden oder nicht übereinstimmenden Elemente zweier Mengen zurückliefern.

mfg
Harald

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 09:15
von BlackJack
@bfm: „In der Regel will man ja aber zu zwei oder mehr Symptomen die übereinstimmenden Heilmittel herausfinden.”

Ja, genau *das* war doch hier die Frage! Und die Zeilen 20-22 in meiner Lösung lesen sich kompliziert? Vielleicht nicht sofort verständlich wenn man die zwei verwendeten Funktionen, den `set`-Datentyp, und das Syntaxkonstrukt Generatorausdruck nicht kennt, aber kompliziert ist dieser eine Ausdruck IMHO nicht wirklich.

Ob es einfacher wird, wenn man einem Programmieranfänger *zusätzlich* mit SQL eine weitere Sprache und alles was Datenbanken und Datenbankentwurf so mitbringt auflädt, bezweifle ich. Das hier ist jedenfalls kein Problem wo ich sagen würde mit einer relationalen Datenbank wäre es einfacher zu lösen als mit Datenstrukturen und Python-Code alleine. Wenn man das in eine DB steckt und die Anfrage in SQL formuliert *vermeidet* man ja sogar sich mit den entsprechenden Python-Datenstrukturen zu beschäftigen, also den Umgang damit zu lernen.

Zusatzinformationen zu den Placebos kann man jedenfalls auch in dem Wörterbuch speichern. Und wenn man das flexibler haben möchte als hart im Quelltext kodiert, bietet sich JSON als Format an.

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 11:00
von Eliazz
@bfm:
Jap die Idee hatte ich bereits, aber es ist nicht (wirklich) umsetzbar, aus zwei Gründen:

1. Wie Blackjack bereits sagte: Ich bin ein blutiger Anfänger und habe nicht das nötige Know-How für SQL einbindung.
2. Am Ende gibt es für jedes Symptom bis zu 50 mögliche Mittel, welche wiederum ihre eigenen Wertigkeiten haben, das wird dann schwierig in einer Tabelle. Vorallem wenn die Anzahl der Mittel nicht immer übereinstimmt.

Ich bin jetzt erstmal soweit gekommen, dass das Programm wie gewünscht funktioniert!
Ich häng es mal an und hole mir gerne Kritik ab! :)
Mein eigentliches Hauptproblem war folgendes: Ich wusste nicht, dass man eine Variable nicht einfach mit '=' auf den Wert einer anderen setzen sollte, wenn man eine Kopie braucht. Jetzt kann ich die Möglichkeit benutzen die Blackjack mir gezeigt hat: a = b[:], um eine Copy zu erstellen. Vielen dank Blackjack, du hast als einziger den Nagel wirklich auf den Kopf getroffen.

Aber ihr habt mir alle sehr geholfen, auch Eydu, obwohl das ein bischen sehr viel auf einmal war, an Kritik :lol: Das muss ich mir nochmal ganz in Ruhe anschauen.

Vielen Dank, und MFG Eliazz

-Edit-
Hab mich mit den Beiträgen gerade ein bischen vertan, Snafu, du hast natürlich auch einen großen Teil dazu beigetrage, also großes Dankeschön auch an dich :)

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 11:27
von Eliazz
Hier mein neuer Code, fehlt jetzt nurnoch grafische Umsetzung :)

Code: Alles auswählen

# Ab hier das Verzeichnis bearbeiten:

symptome_verzeichnis = {
    'Abmagerung' : [ [ 3 , 2 , 2 , 1 ] , 'ars' , 'merc' , 'lyc' , 'nat-m' ]  ,
    'Asthma' : [ [ 2 , 2 , 2 , 3 ] , 'ars' , 'nat-m' , 'lyc' , 'phos' ] ,
    'Kälte' : [ [ 3 , 2 , 3 , 1 ] , 'ars' , 'merc'  , 'sil' , 'lyc' , ] ,
    'Hitze' : [ [1 , 3 , 2 , 2 , 3, 2] , 'ars' , 'bell' , 'nat-m' , 'puls' , 'sulf' , 'sulf-ac' ]
    }

# Programmcode...

symptome_run = {}

while True:
    symptom = input ('Gib ein Symptom ein: ')
    if symptom in ('0', '-','/','q','_','x','#','.',','):
        break
    elif symptom in symptome_verzeichnis:
        symptome_run[symptom] = symptome_verzeichnis[symptom]
    else:
        print('Fehlerhafte Eingabe, Großschreibung beachten!')

mittel_überprüfen_list = max(symptome_run.values(), key = len)
cop_mittel_überprüfen_list = mittel_überprüfen_list[:]
del cop_mittel_überprüfen_list[0]

wirksame_mittel_list  = []
wertigkeiten_list = []
counter = 0
for überprüfung_mittel in cop_mittel_überprüfen_list:
    r_counter = 0
    zsm_rechnen = 0
    for überprüfung_symptome in symptome_run:
        if überprüfung_mittel in symptome_run[überprüfung_symptome]:
            r_counter += 1
            index = symptome_run[überprüfung_symptome].index(überprüfung_mittel) - 1
            zsm_rechnen += symptome_run[überprüfung_symptome][0][index]
    if r_counter == len(symptome_run):
        wirksame_mittel_list.append(überprüfung_mittel)
        wertigkeiten_list.append(zsm_rechnen)
    counter += 1

for ausgabe in range (0, len(wirksame_mittel_list)):
    print(wirksame_mittel_list[ausgabe], ', mit einer Wertigkeit von',  wertigkeiten_list[ausgabe])
    

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 12:08
von BlackJack
@Eliazz: Die Kopie einer Liste mit der „slice”-Syntax ``shallow_copy = original[:]`` funktioniert zwar, ich würde aber zu der Alternative ``shallow_copy = list(original)`` greifen. Da ist es zum einen einfacher nachzulesen was passiert, weil man nach `list()` besser in der Dokumentation suchen kann, und zum anderen ist es dann einfacher `original` durch andere Container-Objekte zu ersetzen bei denen die „slice”-Syntax nicht funktioniert, bei denen man aber über die einzelnen Elemente iterieren kann. `set`\s zum Beispiel.

Du willst Dich ja nicht mit DB-Entwurf beschäftigen, darum nur der Vollständigkeit halber: Wieviele mögliche Mittel es pro Sympton gibt ist egal, denn das wird nicht so gespeichert wie Du Dir das offensichtlich vorstellst. Die Symptome bekommen eine Tabelle, die Mittel bekommen eine eigene Tabelle, und dann gibt es noch eine Tabelle die Symptome und Mittel einander zuordnet (und im erweiterten Fall noch die Wertigkeit enthält).

Zur Kritik am neuen Code: Es gilt vieles von meinem letzten Beitrag noch. Insbesondere solltest Du Dir `set`\s anschauen.

Es sind ja noch mehr Zeichen zum Beenden der Eingabe hinzugekommen. Das würde ich ja komplett streichen und auf die Leereingabe als Endkennzeichen umstellen. Warum so viele, teils komische Alternativen erlauben? Noch benutzerfreundlicher würde es wenn man dem Benutzer die Alternativen zur Auswahl anbieten würde. Dann muss er nicht wissen oder raten welche Symptome das Programm versteht und welche nicht.

Bei der erweiterten Datenstruktur fällt auf, dass Du zusammengehörige Daten in ”parallelen” Strukturen speicherst. Die Wertigkeit und das Mittel gehören zusammen. Du sagst ja selbst es kann viel mehr Mittel geben. Dann überleg mal wie nervig und fehleranfällig das wird die Wertigkeit anzupassen. Dann musst Du anfangen zu zählen an welcher Stelle ein Mittel steht und dann noch mal in der Liste mit den Wertigkeiten bis zu der Stelle zählen wo die dazugehörige Wertigkeit steht. Das macht arbeit und kann schnell mal daneben liegen. Das Löschen der Wertigkeit bei der Verarbeitung ist auch äusserst undurchsichtig. Ich habe jedenfalls eine Weile gebraucht das zu verstehen. Im Grunde ist die Datenstruktur jetzt auch zu kompliziert um da einfach mit einem grossen Hauptprogramm drauf zu operieren. Man sollte anfangen sprechend benannte Funktionen zu verwenden. Und auf lange Sicht anfangen eigene Datentypen zu schreiben. Zum Beispiel für die Mittel. Oder zumindest ein `collections.namedtuple` für die Mittel zu erstellen, damit man nicht mit nichtssagenden Indexwerten auf die Bestandteile zugreifen muss. Oder vielleicht für die Verarbeitung besser: Statt den Symptomen eine Liste zuzuordnen, jedem Symptom ein Wörterbuch zuordnen welches Mittel auf Wertigkeit abbildet.

In der Eingabeschleife sammelst Du jetzt zu viele Daten. Warum nicht mehr einfach nur die Namen der Symptome in einer Liste? Von `symptome_run` verwendest Du letztendlich im ganzen weiteren Programm nur die Werte, nie die Schlüssel, ausser um an die Werte zu kommen.

`counter` wird nirgends verwendet! Dafür hätte man auch besser die `enumerate()`-Funktion verwendet, statt den manuell zu initialisieren und hochzuzählen.

In der Ausgabe ist wieder das „anti pattern” mit der Schleife über Indexwerte statt `zip()` beziehungsweise wäre das nicht nötig wenn die Daten nicht in parallelen Listen stehen würden.

Bevor Du an eine grafische Umsetzung denkst, brauchst Du noch Funktionen und objektorientierte Programmierung (OOP). Ohne ist IMHO keine nicht-triviale GUI möglich.

Der nächste Schritt wäre dann also eher das Ganze sinnvoll in Funktionen aufzuteilen. Eine Hauptfunktion die nach dem Muster in meiner letzten Lösung aufgerufen wird, und dann vielleicht in Eingabe, Verarbeitung, und Ausgabe in einzelnen Funktionen aufteilen. Ich verstehe die Verarbeitung bei Dir nicht. Ich habe da jetzt fast 8 Minuten drauf geschaut und bin nur verwirrt. Warum wird zum Beispiel bei der Berechnung von `index` am Ende 1 abgezogen? Das macht für mich keinen Sinn.

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 12:54
von Eliazz
Haha ja, haste recht, das die Wertigkeiten am Anfang der Liste stehen ist auf Dauer wohl ein wenig kompliziert, aber ich wollte nicht ineinandergeschachtelte Dics machen, weil das IMO aufwendiger wäre, oder? Ich verstehe nicht so ganz was du meinst mit "selber schreiben" gibts dazu ein Tutorial? Bzw: Wie kann ich das mit den Wertigkeiten so machen, dass es am einfachsten ist?

Ja das mit dem index - 1? :P
naja überleg mal:

Code: Alles auswählen

'Asthma' : [ [ 2 , 2 , 2 , 3 ] , 'ars' , 'nat-m' , 'lyc' , 'phos' ]
Wenn ich jetzt die zugehörige Wertigkeit für Asthma herausfinden möchte... Dann ist der Index in der Hauptliste ja 1. Aber Es ist nicht das 2te sondern das erste Element, also eine 0... Denn das erste Element in der Liste ist ja die Wertigkeiten Liste. Die 1 ('ars') soll ja der 0 in der geschachtelten Liste entsprechen, desshalb -1... Das trifft immer zu, fand ich also keine schlechte Idee.. oder geht das einfacher??
Also diesen Schritt fand ich noch am plausibelsten in meinem Code... :P

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 13:02
von EyDu
Wie kommst du auf verschachtelte Dictionaries, BlackJack hat dir doch schon den Hinweis auf (Named-)Tuples gegeben:

Code: Alles auswählen

    'Asthma' : [('ars', 2) , ('nat-m', 2) , ('lyc', 2) , ('phos', 3) ]
Du solltest dich noch einmal genauer mit den Datentypen in Python beschäftigen.

Im Allgemeinen ist der Code schon besser geworden, aber wirf doch noch einmal einen Blick auf BlackJacks und meine langen Beiträge. Da gibt es noch so einiges, was auf deinen jetzigen Code noch immer anwendbar ist.

Edit: Code-Tags

Re: merkwürdige for - Schleife

Verfasst: Mittwoch 9. Oktober 2013, 13:04
von Eliazz
Ah okay, danke, werd ich machen :)