Seite 1 von 1

Nach Reihenfolge replacen

Verfasst: Samstag 12. Dezember 2020, 16:54
von MupfSpace
Hallo,

angenommen ich habe einen String: "##########"
und eine Liste: [".", ","].

Jetzt möchte ich alle "#" durch die Elemente in der Liste ersetzen, allerdings dings nicht nur mit einem der beiden oder in einer zufälligen Reihenfolge sonder in der Reinfolge, wie sie in der Liste sind, also in diesem Fall: ".,.,.,.,.,"

Wie mache ich das?

string.replace(liste) funktioniert nicht (ist aber eigentlich auch klar)

Re: Nach Reihenfolge replacen

Verfasst: Samstag 12. Dezember 2020, 17:09
von pillmuncher
Das hier könnte hilfreich sein: https://docs.python.org/3/library/itert ... ools.cycle

Außerdem musst du vermutlich den String in einer for-Schleife zeichenweise durchgehen und einen neuen String Schritt für Schritt selbst erzeugen.

Re: Nach Reihenfolge replacen

Verfasst: Samstag 12. Dezember 2020, 18:29
von __blackjack__
Kommen da auch andere Zeichen als "#" in der ursprünglichen Zeichenfolge vor?

Re: Nach Reihenfolge replacen

Verfasst: Samstag 12. Dezember 2020, 18:46
von MupfSpace
__blackjack__ hat geschrieben: Samstag 12. Dezember 2020, 18:29 Kommen da auch andere Zeichen als "#" in der ursprünglichen Zeichenfolge vor?
Jain,
es kommen neben # noch lehrzeichen und \n vor, aber die sollen nicht replaced werden. Aber sonst nur #

Re: Nach Reihenfolge replacen

Verfasst: Samstag 12. Dezember 2020, 20:14
von python-neophyte
1. Technisch gesehen kannst du keine Zeichen im String "ersetzen", String ist ein unveränderlicher Datentyp. Du kannst nur einen neuen String erzeugen (in Python 3.x)

2. Wenn der String und die Liste die gleiche Länge hätten, hättest du die Funktion zip() verwenden können. Da sie das aber nicht sind, hier ein Schnipsel, der funktioniert.

Code: Alles auswählen

a = ['.', ';']
b = "odalksdjalkdj"
c = ""
for i in range(len(b)):
	c += a[i % len(a)]
print(c)
>> '.;.;.;.;.;.;.'


Re: Nach Reihenfolge replacen

Verfasst: Samstag 12. Dezember 2020, 22:43
von __blackjack__
@python-neophyte: Ich sehe nicht wie das eine Lösung sein sollte, denn da sind ja nicht mal "#"-Zeichen in `b`. Und das was da ineffizient mit einer Schleife gemacht wird, könnte man auch in einem Ausdruck haben:

Code: Alles auswählen

In [298]: a                                                                     
Out[298]: ['.', ';']

In [299]: b                                                                     
Out[299]: 'odalksdjalkdj'

In [300]: ("".join(a) * ((len(b) + 1) // 2))[: len(b)]                          
Out[300]: '.;.;.;.;.;.;.'
Man könnte das `re`-Modul zum suchen und ersetzen verwenden:

Code: Alles auswählen

In [301]: b = "## ### # #####\n"                                                

In [302]: import re                                                             

In [303]: from itertools import cycle                                           

In [304]: from functools import partial                                         

In [305]: re.sub("#", partial(next, cycle(a)), b)                               
Out[305]: '.; .;. ; .;.;.\n'

Re: Nach Reihenfolge replacen

Verfasst: Montag 14. Dezember 2020, 12:36
von python-neophyte
__blackjack__ hat geschrieben: Samstag 12. Dezember 2020, 22:43 @python-neophyte: Ich sehe nicht wie das eine Lösung sein sollte, denn da sind ja nicht mal "#"-Zeichen in `b`. Und das was da ineffizient mit einer Schleife gemacht wird, könnte man auch in einem Ausdruck haben:

Code: Alles auswählen

In [298]: a                                                                     
Out[298]: ['.', ';']

In [299]: b                                                                     
Out[299]: 'odalksdjalkdj'

In [300]: ("".join(a) * ((len(b) + 1) // 2))[: len(b)]                          
Out[300]: '.;.;.;.;.;.;.'
Man könnte das `re`-Modul zum suchen und ersetzen verwenden:

Code: Alles auswählen

In [301]: b = "## ### # #####\n"                                                

In [302]: import re                                                             

In [303]: from itertools import cycle                                           

In [304]: from functools import partial                                         

In [305]: re.sub("#", partial(next, cycle(a)), b)                               
Out[305]: '.; .;. ; .;.;.\n'

Dies ist eindeutig eine Art Schulungsfrage für Anfänger. Meine Lösung ist leicht lesbar und erreicht das Ergebnis auf eine klare Art und Weise.

Wenn es zusätzliche Einschränkungen zur ursprünglichen Frage gäbe, z.B. "mach das mit 'list comprehension'" oder "mach das mit functools package", wäre das sinnvoll.

Ich denke nicht, dass es notwendig ist, fortgeschrittenere Techniken für die Lösung dieser einfachen Aufgaben zu verwenden, wenn es nicht explizit gefordert ist.

Re: Nach Reihenfolge replacen

Verfasst: Montag 14. Dezember 2020, 12:52
von __blackjack__
@python-neophyte: Deine Lösung ist keine Lösung, da sie das gestellte Problem nicht löst.

Wenn es um Verständlichkeit geht, würde ich meine Lösung noch wie folgt abändern, damit das nicht so ”magisch” ist, das `next()` das Match-Objekt ”verschluckt”:

Code: Alles auswählen

In [112]: a_cycled = cycle(a)                                                   

In [113]: re.sub("#", lambda match: next(a_cycled), b)                          
Out[113]: '.; .;. ; .;.;.\n'
Sich Teile davon jetzt irgendwie kleinteilig mit Indexerei nachzubasteln wird letztlich auch nicht leichter nachvollziehbar. Man braucht halt nur mehr Code, mehr Variablen, und kann mehr Fehler machen.