Seite 1 von 1

string.replace mit dictionary

Verfasst: Donnerstag 21. Februar 2008, 16:09
von nemomuk
Hallo,

wie kann ich in einem String einzelne "Sequenzen" mit Hilfe eines Dictionarys ersetzen?

Code: Alles auswählen

string = "kosidfmapofkpdsofpjosldlikddgoisdoijfpdsfoidsgpifdolikgzhpokfsigoifdgidomibfdgol"

dict = { "a":"b", "c":"d",....}
string.replace() #und die Schlüssel mit den zugehörigen Werten ersetzen...
Vielen Dank!

Verfasst: Donnerstag 21. Februar 2008, 16:16
von BlackJack
Also wenn das immer ein Zeichen durch ein anderes ersetzen ist, dann schau Dir mal die `translate()`-Methode auf Zeichenketten an.

Verfasst: Donnerstag 21. Februar 2008, 16:22
von nemomuk
Nein ist es nicht..., wenn ich dich richtig verstehe...

Ich will zum Beispiel sowas machen:

Code: Alles auswählen

dict = {

"qwe":"ert",
"fgh":"tzu",

}
Also völlig willkürlich und auch nicht jeden Buchstaben. Und so wie ich das bei translate verstanden habe, muss man da ein table haben mit 256 Zeichen... und alle Zeichen werden ersetzt

Verfasst: Donnerstag 21. Februar 2008, 17:35
von BlackJack
Man könnte sich das mit `re.sub()` etwas basteln. Den regulären Ausdruck aus den Schlüsseln zusammensetzen und als Ersetzung dann eine Funktion, die aus dem Match-Objekt über das Dictionary die Übersetzung heraus sucht.

Verfasst: Donnerstag 21. Februar 2008, 17:55
von mikrokosmos
Ich würde folgende Lösung vorschlagen:

Code: Alles auswählen

In [7]: text = "blubb"

In [8]: d = {"u": "a", "b": "p"}

In [9]: for i in d.iteritems():
   ...:     text = text.replace(*i)
   ...:

In [10]: text
Out[10]: 'plapp'

Verfasst: Donnerstag 21. Februar 2008, 18:04
von BlackJack
Was die Gefahr birgt, dass eine Ersetzung die Zeichenkette so verändert, dass eine folgende Ersetzung zutrifft. Da Dictionaries ungeordnet sind, wäre das nicht einmal deterministisch. Ob diese Gefahr besteht, müsste SchneiderWeisse beantworten.

Verfasst: Donnerstag 21. Februar 2008, 18:06
von CM
Das ist gefährlich, da
a) eine Reihenfolge in einem dict nicht sortiert ist und damit nicht unbedingt immer dieselbe Reihenfolge vorliegt (hängt natürlich vom Problem ab, ob sich das dict ggf. mal ändert oder nicht)
und b) weil es so zu multiplen Austauschen kommen kann - was vielleicht nicht erwünscht ist.

edit: Zu langsam ...

Verfasst: Donnerstag 21. Februar 2008, 18:10
von nemomuk
ja, ich bin erst über pythonchallenge auf diese Frage gekommen und könnte das für ein Projekt gerbauchen...

Jetzt scheitert es ersteinmal hieran:

Code: Alles auswählen

a = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z')
b = ('c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b')
stri = "g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj."
for x, y in zip(a,b):
	stri = stri.replace(x,y)
print stri
Das ganze gibt folgendes aus:
ababbababsbababababababababa etc.

Also nicht wirklich was ich will...

Was ist hieran falsch?

Danke für eure Hilfe!!!

Verfasst: Donnerstag 21. Februar 2008, 18:21
von CM
Du iterierst über Deine Austauspaare und ersetzt jeden Hit im String so lange bis nur noch 'a' und 'b' übrig bleiben.

Wenn Deine Schlüssel immer gleich lang sind, ließe sich auch über mit Schritten gleich der Länge des Schlüssels über den String iterieren. Dann kannst Du ggf. auch ein dict nutzen.

Gruß,
Christian

Verfasst: Donnerstag 21. Februar 2008, 21:52
von nemomuk
für alle dies interessiert:

Code: Alles auswählen

import string
a = "abcdefghijklmnopqrstuvwxyz"
b = "cdefghijklmnopqrstuvwxyzab"
trans = string.maketrans(a,b)
stri = "g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj."
q = stri.translate(trans)
print q
a = raw_input()

Verfasst: Freitag 22. Februar 2008, 01:11
von mitsuhiko

Code: Alles auswählen

import re

def replace_dict(string, replacements):
    regex = re.compile('|'.join(re.escape(a) for a in
                                sorted(replacements, lambda x: -len(x))))
    return regex.sub(lambda m: replacements[m.group(0)], string)
Ungetestet, sollte aber so hinhauen.