Seite 1 von 1

Charactervergleich im String - bringt zufällige Ergebnisse [gelöst]

Verfasst: Mittwoch 29. Januar 2025, 13:33
von Pythagoraze
EDIT:
Sorry.
Ich hab es gerade gesehen, ich habe i =+ 1 statt i += 1 gehabt.
So setzte ich ja i immer nur gleich +1, statt zu iterieren.

Moderation: Lassen wir den Thread/Post stehen, oder löschen wir den?
Sorry, war mir nicht eher aufgefallen.

_______________
Moin.

ich wollte eigentlich nur zwei Strings vergleichen. Und wenn die an den Stellen gleich sind, wollte ich ein Zeichen (hier ne Eins) setzen [ich weiß, dafür gäb es builtin-Funktionen, aber später sollen andere Zeichen verglichen werden ... etwas komplexer, das ganze, aber da das mit Zeichen aus dem Alphabet schon nicht richtig hinhaute, wollte ich es wenigstens auf 01 reduzieren]

Code: Alles auswählen

a = "11001"
b = "01010"
c = ""
d = ""
i = 0
for e in a:  # hätte hier auch for i in range(0, len(a)): machen können, oder for i in range(0, 5): , wollte mir aber etwas Tipparbeit sparen
    if a[i] == b[i]:
        c = c + "1"
    else:
        c = c + "0"
    print(a[i],b[i])
    i =+ 1
print(c)
Ausgabe:
>>> %Run VGL.py
1 0
1 1
1 1
1 1
1 1
01111

Aber egal, wie ich die Strings a, b verändere - die Ergebnisse sind irgendwie immer zufällig.
Oder mir nicht nachvollziehbar.
Was stimmt denn damit nicht? Was mach ich falsch?

Re: Charactervergleich im String - bringt zufällige Ergebnisse [gelöst]

Verfasst: Mittwoch 29. Januar 2025, 15:13
von __blackjack__
@Pythagoraze: Wenn Du schon ``for e in a:`` schreibst um Dir Tipparbeit zu sparen, warum sparst Du Dir das mit dem `i` nicht gleich ganz? Noch mehr Tipparbeit gespart und damit hättest Du auch den Fehler gar nicht gehabt: ``for e, f in zip(a, b):``. Kein `i` mehr. Weder vor der Schleife, noch in der Schleife.

Das mit dem ``+=`` bei Zeichenketten ist nicht so gut, das hat potentiell ein böses Laufzeitverhalten, weil Zeichenketten nicht veränderbar sind. Ungetestet:

Code: Alles auswählen

a = "11001"
b = "01010"
c = "".join(str(int(e == f) for e, f in zip(a, b)))
print(c)
Wobei das auch schräg ist die binäre Oder-Verknüpfung auf Zeichenkettenebene zu lösen (ungetestet):

Code: Alles auswählen

a = 0b11001
b = 0b01010
c = a | b
print(f"{c:05b}")

Re: Charactervergleich im String - bringt zufällige Ergebnisse [gelöst]

Verfasst: Mittwoch 29. Januar 2025, 15:34
von Sirius3
@Pythagoraze: Du programmierst mit sehr einfachen Konstrukten, die die Mächtigkeit von Python nicht nutzen, und deshalb aus sehr viel Code mit sehr vielen Möglichkeiten Fehler zu machen, besteht.
Wenn man einen Index in einer for-Schleife braucht, benutzt man enumerate:

Code: Alles auswählen

a = "11001"
b = "01010"
c = ""
for i, e in enumerate(a):
    if a[i] == b[i]:
        c = c + "1"
    else:
        c = c + "0"
    print(a[i],b[i])
Über einen Index zu iterieren ist aber eh falsch, weil man da zu viele Fehler machen kann. Wenn man zwei Sequenzen hat, über die man gemeinsam laufen möchte, benutzt man `zip`:

Code: Alles auswählen

a = "11001"
b = "01010"
c = ""
for zeichen_a, zeichen_b in zip(a, b):
    if zeichen_a == zeichen_b:
        c = c + "1"
    else:
        c = c + "0"
    print(zeichen_a, zeichen_b)
Zeichenketten setzt man aber nicht Stück für Stück zusammen, sondern speichert erst alles in einer Liste und benutzt am Schluß join:

Code: Alles auswählen

a = "11001"
b = "01010"
ergebnis = []
for zeichen_a, zeichen_b in zip(a, b):
    ergebnis.append(
        "1" if zeichen_a == zeichen_b else "0"
    )
    print(zeichen_a, zeichen_b)
c = "".join(ergebnis)
Für solche Art Schleifen gibt es ein spezielles Konstrukt, das sich List-Comprehension nennt:

Code: Alles auswählen

a = "11001"
b = "01010"
ergebnis = [
    "1" if zeichen_a == zeichen_b else "0"
    for zeichen_a, zeichen_b in zip(a, b)
]
c = "".join(ergebnis)
Den Zwischenschritt "Liste" braucht man eigentlich nicht:

Code: Alles auswählen

a = "11001"
b = "01010"
c = "".join(
    "1" if zeichen_a == zeichen_b else "0"
    for zeichen_a, zeichen_b in zip(a, b)
)
Und jetzt kann man noch die spezielle Eigenschaft von Wahrheitswerten nutzen, dass int(True) == 1 und int(False) == 0:

Code: Alles auswählen

a = "11001"
b = "01010"
c = "".join(
    str(int(zeichen_a == zeichen_b))
    for zeichen_a, zeichen_b in zip(a, b)
)
oder wenn man viele Klammern mag:

Code: Alles auswählen

from operator import eq

a = "11001"
b = "01010"
c = "".join(map(str, map(int, map(eq, a, b))))

Re: Charactervergleich im String - bringt zufällige Ergebnisse [gelöst]

Verfasst: Mittwoch 29. Januar 2025, 18:24
von DeaD_EyE
Hoffentlich sind die Zeichenketten immer gleich lang. Wenn sie das sein müssen, würde ich bei der Funktion zip() noch strict=True nutzen. Das wirft dann einen ValueError.
ValueError: zip() argument 2 is longer than argument 1