Seite 1 von 2

Code-Hilfe

Verfasst: Freitag 4. Februar 2005, 19:08
von Gast
Hallo Leute,
ich habe ein Problem...bzw. ich verstehe nicht warum es so ist wie es ist...

Ich habe einen teil aus meinem Programm rausgeholt und ein klein wenig umgeschrieben...
trotzdem passiert hier dasselbe Problem.Und zwar verstehe ich nicht warum bei dem folgenden Code nur einmal OK ausgegeben wird...

Code: Alles auswählen

import string

list = [["A",2],["B",4],["I",6],["L",8],["A",2],["T",6],["C",4],["A",2]]

cmp_tupel = list[0]
cmp_st = cmp_tupel[0]
cmp_val = cmp_tupel[1]

duplicate = "false" #testing if cmp_tripel has more than one deposit in ref_file
for tupel in list:

        ref_st = tupel[0]
        ref_val = tupel[1]

        if cmp_st  == ref_st:
                in_List = "true"
                if duplicate == "false":
                        if cmp_val == ref_val:
                                duplicate = "true"
                                print "OK"

                        else:
                                print "DIFFERENT"

                else:
                        if cmp_val == ref_val:
                                print "OK DUPLICATE"
                        else:

                                print "DIFFERENT DUPLICATE"



        list.remove(tupel)
        print list
Die Ausgabe liefert:
OK
[['B', 4], ['I', 6], ['L', 8], ['A', 2], ['T', 6], ['C', 4], ['A', 2]]
[['B', 4], ['L', 8], ['A', 2], ['T', 6], ['C', 4], ['A', 2]]
OK DUPLICATE
[['B', 4], ['L', 8], ['T', 6], ['C', 4], ['A', 2]]
[['B', 4], ['L', 8], ['T', 6], ['A', 2]]

Aber eigentlich müssten doch zwei DUPLICATE drin sein oder???

Verfasst: Freitag 4. Februar 2005, 19:25
von Dookie
Hi Gast,

ich hab dein erstes Post editiert so, daß der source wieder lesbar ist.

Trotzdem ist mir dein Code nicht ganz klar, davon abgesehen sind mir ein paar sehr seltsamen Eigenheiten aufgefallen.
1. wofür importierst du string ?
2. nenne die Liste bitte nicht list, list ist eine Builtinklasse.
3. duplicate = "false" warum als String? es gibt doch die Boolewerte True und False.

Was soll das Script eigentlich machen? Ich blick da genausowenig durch wie der Pythoninterpreter.


Gruß

Dookie

Verfasst: Freitag 4. Februar 2005, 19:32
von Gast
Hi dookie,
danke für deine HIlfe.

Ehm ok string nicht mehr importieren...
Boolwerte...ja hmm hast recht.... :oops:

Was das skript machen soll...
einfach OK ausgeben wenn ein Element in dem fall A 2
mit einem aus der Liste übereinstimmt.
wenn es dann nochmal vorkommt also wenn der string und der wert gleich sind dann OK Duplikat ausgeben
Und wenn nur der string also das "A" vorkommt und der wert verschieden ist nach dem es mal OK gab dann soll DIFFERENT Duplikat vorkommen.

naja...
ich geb zu es ist bisschen komisch aber im grunde geht es mir ums prinzip...

der interpreter müsste doch so oft das duplikat angeben. wie es auch vorkommt....wieso tut er das nicht???

Verfasst: Freitag 4. Februar 2005, 19:47
von Leonidas
Das kann man mit sets lösen, issubset() ist wohl das was du suchst.

^^ Ach, schmarrn. Das ist nicht der Aufgabe Lösung. Aber ich überlege mal.

Verfasst: Freitag 4. Februar 2005, 19:58
von Gast
Hmm irgendwie begreife ich das nicht:

So gehts:

der ausschnitt von oben:

Code: Alles auswählen

 if duplicate == False: 
                        if cmp_val == ref_val: 
                                duplicate = True 
                                print "OK" 
 
                        else: 
                                print "DIFFERENT" 
 
 [b]if duplicate == True:[/b] 
Das versteh ich nicht...

Verfasst: Freitag 4. Februar 2005, 20:25
von Leonidas
Hier mal eine Lösung von Leonidas, dem User mit dem kompliziertesten Quellcodes in dem ganzen Forum.

Code: Alles auswählen

#!/usr/bin/env python
# -*- encoding: latin-1 -*-

l = [["A", 2], ["B", 4], ["I", 6], ["L", 8], ["A", 2], ["T", 6], ["C", 4], ["A", 3]] 
l.sort()
#print l
gotchars = {}

for entry in l:
    #print entry
    try:
        if not entry[1] in gotchars[entry[0]]:
            print 'DIFFERENT DUPLICATE'
        else:
            print 'OK DUPLICATE'
        gotchars[entry[0]].append(entry[1])
        
    except KeyError:
        if l.count(entry) > 1:
            print 'OK'
        else:
            print 'DIFFERENT'
        gotchars[entry[0]] = [entry[1]]

#print gotchars
Es hilft vielleicht wenn du die prints auskommentiertst den Code zu verstehen. Bei Fragen melde dich ruhig.

Wie ich mich ja schon korrigierte, geht das mit sets nicht, ich habe mich geirrt. Sets würden die Liste etwas plätten, dass nur noch gleiche Werte vorhanden wären.

Verfasst: Freitag 4. Februar 2005, 20:48
von Gast
Danke Leonidas für deine HIlfe.

Öhm was genau macht dieses KeyError???
Noch nie gesehen...

Verfasst: Freitag 4. Februar 2005, 21:07
von Leonidas
Anonymous hat geschrieben:Danke Leonidas für deine HIlfe.
Geht es? *freu*
Anonymous hat geschrieben:Öhm was genau macht dieses KeyError???
Noch nie gesehen...
KeyError ist eine eingebaute Exception, auf deutsch eine Ausnahme. Sie wird aufgerufen, wenn man bei einem Dictionary (das gotkeys ja ist) versucht auf ein Element (in diesem Fall entry[0]) zuzugreifen, dieses aber nicht existiert. Das habe ich abgefangen, da das heißt, dass wir diesen Buchstaben (entry[0]) doppelt haben (also: OK) oder dass es ein anderer Buchstabe ist (also: DIFFERENT).

Verfasst: Samstag 5. Februar 2005, 16:35
von Gast
Ah ok....
ich sehe ich muss noch viel lernen ;)

Danke vielmals!

Verfasst: Samstag 5. Februar 2005, 18:53
von Gast
Hallo Leonidas, ich bins nochmal...
also dein Beispiel kann ich nachvollziehen....ob ichs selbst so hinbekommen hätte glaube ich nicht ;)

trotzdem würde ich gerne verstehen WARUM es bei einem solchen Code:

Code: Alles auswählen

cmp = ["A",2]
ref_list = [["A",2],["A",3],["A",6],["F",8]]

dup = False
for tupel in ref_list:
        
        if ((cmp[0] == tupel[0]) & (dup == False)):
                if cmp[1] == tupel[1]:
                        dup = True
                        print "OK"
                        ref_list.remove(tupel)
                        continue
                if cmp[1] != tupel[1]:
                        print "DIFFERENT"
                        ref_list.remove(tupel)
                        continue

        if ((cmp[0] == tupel[0]) & (dup == True)):
                if cmp[1] == tupel[1]:
                        ref_list.remove(tupel)
                        continue
                if cmp[1] != tupel[1]:
                        print "DIFFERENT DUPLICATE"
                        ref_list.remove(tupel)
                        continue
Probleme gibt.
Die Ausgabe die ich erwarten würde wäre:
OK
DIFFERENT DUPLICATE
DIFFRERENT DUPLICATE

Aber es kommt:
OK
DIFFERENT DUPLICATE

Immer wenn ich ein tupel mit gleichem Buchstaben in diesem Fall "A" hintereiander in die Liste gebe überspringt er das zweite sobald er das erste bearbeitet hat....
Das verstehe ich nicht. Eigentlich müsste er doch allle Elemente durchlaufen.

Wenn man zwishcen die zwei "A" Tupel irgendwas anderes rein tut funktionierts....

Irgendwie bin ich schwer von Begrifff.............

Verfasst: Samstag 5. Februar 2005, 20:47
von Leonidas
Sag mal, kommst du aus der Curled Braces Sprachenecke?
Bei if musst du keine Klammern nutzen, und statt & besser and, das gibt mehr den CHarakter der Spache wieder.

Deinen Code guck ich mir an, bin aber vermutlich erst morgen Abend wieder im Forum, also müsstest du dich etwas gedulden.

Verfasst: Samstag 5. Februar 2005, 22:19
von BlackJack
Anonymous hat geschrieben: trotzdem würde ich gerne verstehen WARUM es bei einem solchen Code:

Code: Alles auswählen

for tupel in ref_list:
        
        if ((cmp[0] == tupel[0]) & (dup == False)):
                if cmp[1] == tupel[1]:
                        dup = True
                        print "OK"
                        ref_list.remove(tupel)
                        continue
[...]

Immer wenn ich ein tupel mit gleichem Buchstaben in diesem Fall "A" hintereiander in die Liste gebe überspringt er das zweite sobald er das erste bearbeitet hat....
Das verstehe ich nicht. Eigentlich müsste er doch allle Elemente durchlaufen.
Ich habe den Code mal soweit verstümmelt, dass man die wichtigen Sachen gerade noch sieht. Auf den Punkt gebracht: Du entfernst Elemente aus einer Liste während Du darüber läufst! Damit änderst Du die Länge der Liste und alle Elemente nach dem Entfernten rücken eins nach vorne. Und dabei "überspringst" Du dann welche. Das unter dem aktuellen Pointer, den Python intern benutzt, ist nämlich um einen Platz nach vorn gerutscht und wird somit im nächsten Durchlauf nicht betrachtet.

Verfasst: Sonntag 6. Februar 2005, 17:19
von Gast
Hallo,
wow....danke euch.

Hmm black....ich finde es halt seltsam dass das Programm eigentlich funktioniert solange eben keine zwei gleiche Elemente aufeinander folgen....
Damit würde es doch heißen dass der Pointer intern nicht durcheinander kommt ...
Und da das removen von einem Objekt immer das erste rauslöscht finde ich es komisch dass eine derartige Inkonsistenz zustande kommt....

@ Leonidas...
Danke für deine Hilfe....
Warum ich kein and statt & benutze ? Naja....
Bins irgendwie von Java / C gewohnt ;o)

Irgendwie finde ich es für mich viel übersichtlicher......ist halt geschmackssache....

Danke für deinen Hilfscode....dann ;o)

Verfasst: Sonntag 6. Februar 2005, 17:29
von Leonidas
Anonymous hat geschrieben:Warum ich kein and statt & benutze ? Naja....
Bins irgendwie von Java / C gewohnt ;o)

Irgendwie finde ich es für mich viel übersichtlicher......ist halt geschmackssache....
Nicht ganz, denn & ist ein binärer Operator, and aber ein logischer, und du brauchst dort ja logische. Das die beiden in diesem Fall das gleiche ergeben, muss ja nicht heißen, das das die Regel ist. Und dann wirst du dich massiv wundern warum es nicht geht.
siehe auch: Operatoren.

Außerdem gibt es in Python eine relativ starke Style Konvention, so dass viele als erstes mal deinen Code entJavaern würden :)

Verfasst: Sonntag 6. Februar 2005, 17:58
von Gast
Lol.......
Peinlich....
dachte & wäre der logische.....

Danke Leo....

Verfasst: Sonntag 6. Februar 2005, 18:18
von Gast
Hmm
es liegt anscheinend wirklcih am remove.....

wenn ich nicht remove dann fuktionierts.
Hmm wie könnte ich das denn umgehen?

Meine Liste muss leider kürzer werden also die Elemente die ich bereits abgearbeitet habe muss ich löschen...

Verfasst: Sonntag 6. Februar 2005, 18:49
von Leonidas
Eine zweite Liste (identische) erstellen (kopieren) und aus dieser die Werte löschen. Wäre mein Vorschlag, so aus dem Bauch heraus. Nicht schön, kommt mir aber einfach zu programmieren vor.

Verfasst: Montag 7. Februar 2005, 00:07
von BlackJack
Ich würde es umgekehrt machen, also die Liste kopieren, über die Kopie iterieren und aus der originalen Liste löschen. Im anderen Fall macht sich das Löschen ja nicht "nach aussen" bemerkbar.

Wenn die Funktion die Liste ohne die Duplikate als Rückgabewert haben soll, dann ist es aber schneller am Anfang eine leere Ergebnisliste anzulegen und in der Schleife immer die "guten" Elemente anzuhängen und die "bösen" einfach wegzulassen. Vereinfacht so:

Code: Alles auswählen

def foo(sequence, sample):
    result = list()
    for element in sequence:
       if good(element):
           result.append(element)
       else:
           print "Duplikat"
    return result

Verfasst: Montag 7. Februar 2005, 00:18
von BlackJack
Anonymous hat geschrieben:Hmm black....ich finde es halt seltsam dass das Programm eigentlich funktioniert solange eben keine zwei gleiche Elemente aufeinander folgen....
Damit würde es doch heißen dass der Pointer intern nicht durcheinander kommt ...
Und da das removen von einem Objekt immer das erste rauslöscht finde ich es komisch dass eine derartige Inkonsistenz zustande kommt....
Das ist nicht wirklich Inkonsistent. Nehmen wir mal an wir wollen alle 2en in einer Schleife aus einer Liste löschen. Die erste Zahl gibt immer den Schleifen-Index an, also auf welches Element zugegriffen wird, dann folgt die Liste und ich mache einen Stern unter das aktuelle Element:

Code: Alles auswählen

0. [1,2,2,3]
    *
1. [1,2,2,3]  # Hui wir haben eine 2 gefunden also...
      *
2. [1,2,3] # entfernen und zum nächsten Schritt.
        *
Und siehe da, durch das Aufrücken aller Elemente nach vorne und das gleichzeitige Weitersetzen des Pointers wird, die zweite 2 übergangen. Wenn die letzten beiden Zahlen vertauscht wären, dann wäre uns die 3 entgangen und wir würden die 2 betrachten und entfernen. Damit wäre dann auch geklärt, warum Dein Code scheinbar funktioniert, wenn Du ein Element dazwischen einfügst. Dieses Element wird aber nie überprüft.

Verfasst: Montag 7. Februar 2005, 16:45
von Gast
Vielen Dank an Euch und auch an Black!
Ich denke mir ist es vieles klarer. Habe wieder was dazugelernt ;)

Ja das mit der Inkonsistenz bzw. Konsistenz leuchtet mir jetzt ein...Und das mit dem Pointer etc....wow!Danke Black für die Erklärung.

Ich habe mein Problem einfach anders gelöst. Für jedes Element einen Bool Wert mitschleppen und am Ende alle mit dem einen Wert rausziehen....so in der Art. Vielleicht nicht ganz effizient aber es funktioniert ;)

Danke nochmals für eure HIlfe....
Dieses Forum ist immer wieder super!!!