2009-06-02 3 views
6

In PHP haben Sie preg_replace($patterns, $replacements, $string), wo Sie alle Ihre Substitutionen auf einmal machen können, indem Sie eine Reihe von Mustern und Ersetzungen übergeben.Können Sie beim Ersetzen von Zeichenfolgen in Python ein Wörterbuch übergeben?

Was ist das Äquivalent in Python?

Ich bemerkte, dass die Zeichenfolge und Wieder Funktionen replace() und sub() Sie Wörterbücher nicht nehmen ...

Edited basierend auf einem Kommentar von Rick zu klären: die Idee, einen dict mit Schlüssel zu haben, ist darauf zu achten als reguläre Ausdrücke Muster, wie '\d+S', und (hoffentlich) konstante String-Werte (hoffentlich ohne Rückbezüge). Bearbeiten Sie nun meine Antwort entsprechend (d. H. Um die eigentliche Frage zu beantworten).

Antwort

10

am nächsten ist wahrscheinlich:

somere.sub(lambda m: replacements[m.group()], text) 

zum Beispiel:

>>> za = re.compile('z\w') 
>>> za.sub(lambda m: dict(za='BLU', zo='BLA')[m.group()], 'fa za zo bu') 
'fa BLU BLA bu' 

mit einem .get statt [] -indexing, wenn Sie einen Standard für Spiele liefern mögen, die in replacements fehlen.

Edit: was Rick wirklich will, ist ein Diktat mit Schlüsseln zu haben als reguläre Ausdruck Muster, wie '\d+S', und (hoffentlich) konstante String-Werte (hoffentlich w/o Rückschlüsse) genommen werden. Das Kochbuch Rezept kann für diesen Zweck angepasst werden:

def dict_sub(d, text): 
    """ Replace in 'text' non-overlapping occurences of REs whose patterns are keys 
    in dictionary 'd' by corresponding values (which must be constant strings: may 
    have named backreferences but not numeric ones). The keys must not contain 
    anonymous matching-groups. 
    Returns the new string.""" 

    # Create a regular expression from the dictionary keys 
    regex = re.compile("|".join("(%s)" % k for k in d)) 
    # Facilitate lookup from group number to value 
    lookup = dict((i+1, v) for i, v in enumerate(d.itervalues())) 

    # For each match, find which group matched and expand its value 
    return regex.sub(lambda mo: mo.expand(lookup[mo.lastindex]), text) 

Beispiel für die Verwendung:

d={'\d+S': 'wot', '\d+T': 'zap'} 
    t='And 23S, and 45T, and 66T but always 029S!' 
    print dict_sub(d, t) 

aussendet:

And wot, and zap, and zap but always wot! 

Sie vermeiden lookup bauen könnte und nur mo.expand(d.values()[mo.lastindex-1]) verwenden, aber das könnte sein ein bisschen langsam, wenn d ist sehr groß und es gibt viele Übereinstimmungen (Sorry, habe nicht beide Ansätze genau gemessen/bewertet, so ist dies nur eine Vermutung;-).

+0

sein Dieser unterstützt nur einen regulären Ausdruck, ich glaube, Sie können Gehen Sie nicht einfacher als die Funktion, die ich von ActiveState übernommen habe, für den Fall, dass Sie sowohl ein Ersatz- als auch ein Muster-Diktat wünschen. Können Sie? –

+0

Für mehr String-Ersetzungen in einem Durchgang durchgeführt wird, wie ich das Rezept, das ist, warum ich es für das Python-Kochbuch aufgenommen, siehe http://books.google.com/books?id=Q0s6Vgb98CQC&pg=PA38&dq=xavier+defrang&ei=k5okSvPbNILClQSk2LWvBw (Ich denke, dass die Diskussion, die Anna und ich dort hinzufügten, einen gewissen Mehrwert bringt, aber ich bin natürlich voreingenommen. Ich habe versucht, direkter auf die genaue Frage zu antworten - eine ganz allgemeine RE und ein gegebenes Ersatzdiktat. –

+0

Ich denke, die ursprüngliche Frage wird besser durch das Rezept beantwortet, weil PHP preg_replace sowohl viele Regexps und Ersetzungen akzeptiert. –

-2

Es ist leicht genug, um dies zu tun:

replacements = dict(hello='goodbye', good='bad') 
s = "hello, good morning"; 
for old, new in replacements.items(): 
    s = s.replace(old, new) 

finden Sie viele Orte finden, wo PHP-Funktionen ein Array von Werten annehmen und es gibt keine direkten Python äquivalent, aber es ist viel einfacher, mit Arrays zu arbeiten (Listen) in Python ist es also weniger ein Problem.

+0

Sie statt dict.items dict.iteritems verwenden, pro PEP290 möchten http://www.python.org/dev/peps/pep- 0290/# Loop-Over-Wörterbücher – NicDumZ

+5

Mag es nicht. Es ist nicht garantiert, dass dict.items() in einer bestimmten Reihenfolge steht, so dass der resultierende Austausch unvorhersehbar ist. Wenn in Ihrem Beispiel zum Beispiel "Hallo" zuerst verarbeitet wird, lautet die resultierende Zeichenfolge "badbye, bad morning"; Ansonsten ist es "Auf Wiedersehen, schlechter Morgen". – Triptych

+0

@Triptych: Netter Fang. –

-1

Hier ist eine einfache Art und Weise

mynewstring=reduce(lambda a,(b,c): a.replace(b, c), mydict.items(), mystring) 
+0

Das scheitert, wenn mydict '{'a': 'b', 'b': 'a'}' – Eric

+0

@Eric das ist ein Preis, den wir dafür bezahlen, einfach zu sein. Diese einfache Methode simuliert verkettete Ersetzungen. –

+1

Eine einfache Lösung ist nutzlos, wenn sie auch nicht funktioniert – Eric

-2

Sie können das Wörterbuch reduzieren Verwendung passieren, während Zeichenfolge in Python zu ersetzen. Betrachten wir das obige Beispiel:

replacement = {'hello' : 'goodbye', 'good' : 'bad' } 

Sie die Zeichenfolge in diesem Format schreiben

s = "%(hello)s, %(good)s morning" 
changed_s = s%replacement 

die Ausgabe von changed_s wird

"goodbye, bad morning" 
+1

-1: Das ist kein String-Ersatz, seine String-Interpolation. – Blair

Verwandte Themen