472 Stimmen

Wie kann man mehrere Teilstrings einer Zeichenkette ersetzen?

Ich möchte die Funktion .replace verwenden, um mehrere Zeichenfolgen zu ersetzen.

Ich habe derzeit

string.replace("condition1", "")

aber ich würde gerne etwas haben wie

string.replace("condition1", "").replace("condition2", "text")

obwohl sich das nicht nach einer guten Syntax anfühlt

Was ist der richtige Weg, um dies zu tun? ähnlich wie in grep/regex können Sie tun \1 y \2 um Felder durch bestimmte Suchbegriffe zu ersetzen

2 Stimmen

Ich habe mir die Zeit genommen, alle Antworten in verschiedenen Szenarien zu testen. Siehe stackoverflow.com/questions/59072514/

4 Stimmen

Die kurze Antwort lautet: Es gibt keinen besseren Weg, dies zu tun.

38voto

Xavier Guihot Punkte 42435

Start: Python 3.8 und die Einführung von Zuweisungsausdrücke (PEP 572) ( := Operator), können wir die Ersetzungen innerhalb eines Listenverständnisses anwenden:

# text = "The quick brown fox jumps over the lazy dog"
# replacements = [("brown", "red"), ("lazy", "quick")]
[text := text.replace(a, b) for a, b in replacements]
# text = 'The quick red fox jumps over the quick dog'

7 Stimmen

Dies ist eine enorme Platzverschwendung, wenn Sie nur das letzte Element benötigen. Verwenden Sie keine Listenauflösungen als Reduzierstücke obwohl die verlinkte Antwort nicht besonders effizient oder nützlich ist, da sie, wie auch diese, Probleme mit der Ersetzungsreihenfolge hat.

35voto

MiniQuark Punkte 43252

Ich habe dies auf der Grundlage von F.J.s ausgezeichneter Antwort getan:

import re

def multiple_replacer(*key_values):
    replace_dict = dict(key_values)
    replacement_function = lambda match: replace_dict[match.group(0)]
    pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
    return lambda string: pattern.sub(replacement_function, string)

def multiple_replace(string, *key_values):
    return multiple_replacer(*key_values)(string)

Einmalige Verwendung:

>>> replacements = (u"café", u"tea"), (u"tea", u"café"), (u"like", u"love")
>>> print multiple_replace(u"Do you like café? No, I prefer tea.", *replacements)
Do you love tea? No, I prefer café.

Da die Ersetzung in nur einem Durchgang erfolgt, ändert sich "café" in "tea", aber nicht zurück in "café".

Wenn Sie dieselbe Ersetzung mehrmals vornehmen müssen, können Sie problemlos eine Ersetzungsfunktion erstellen:

>>> my_escaper = multiple_replacer(('"','\\"'), ('\t', '\\t'))
>>> many_many_strings = (u'This text will be escaped by "my_escaper"',
                       u'Does this work?\tYes it does',
                       u'And can we span\nmultiple lines?\t"Yes\twe\tcan!"')
>>> for line in many_many_strings:
...     print my_escaper(line)
... 
This text will be escaped by \"my_escaper\"
Does this work?\tYes it does
And can we span
multiple lines?\t\"Yes\twe\tcan!\"

Verbesserungen:

  • Code in eine Funktion umgewandelt
  • Unterstützung für mehrere Zeilen hinzugefügt
  • Fehler beim Escaping behoben
  • einfache Erstellung einer Funktion für eine bestimmte Mehrfachersetzung

Viel Spaß! :-)

28voto

Fredrik Pihl Punkte 42950

Ich möchte die Verwendung von String-Vorlagen vorschlagen. Legen Sie die zu ersetzende Zeichenkette einfach in ein Wörterbuch und alles ist fertig! Beispiel aus docs.python.org

>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d)
Traceback (most recent call last):
[...]
ValueError: Invalid placeholder in string: line 1, col 10
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
[...]
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'

2 Stimmen

Ein Nachteil dieses Ansatzes ist, dass die Vorlage alle, und nicht mehr als alle, zu ersetzenden $Strings enthalten muss, siehe aquí

21voto

bgusach Punkte 13550

Hier meine $0,02. Sie basiert auf der Antwort von Andrew Clark, ist nur etwas klarer und deckt auch den Fall ab, dass eine zu ersetzende Zeichenkette eine Teilzeichenkette einer anderen zu ersetzenden Zeichenkette ist (die längere Zeichenkette gewinnt)

def multireplace(string, replacements):
    """
    Given a string and a replacement map, it returns the replaced string.

    :param str string: string to execute replacements on
    :param dict replacements: replacement dictionary {value to find: value to replace}
    :rtype: str

    """
    # Place longer ones first to keep shorter substrings from matching
    # where the longer ones should take place
    # For instance given the replacements {'ab': 'AB', 'abc': 'ABC'} against 
    # the string 'hey abc', it should produce 'hey ABC' and not 'hey ABc'
    substrs = sorted(replacements, key=len, reverse=True)

    # Create a big OR regex that matches any of the substrings to replace
    regexp = re.compile('|'.join(map(re.escape, substrs)))

    # For each match, look up the new string in the replacements
    return regexp.sub(lambda match: replacements[match.group(0)], string)

Es ist in diesem dieser Kernpunkt Wenn Sie einen Vorschlag haben, können Sie ihn gerne ändern.

21voto

James Koss Punkte 523

In meinem Fall brauchte ich eine einfache Ersetzung von eindeutigen Schlüsseln durch Namen, also habe ich mir dies ausgedacht:

a = 'This is a test string.'
b = {'i': 'I', 's': 'S'}
for x,y in b.items():
    a = a.replace(x, y)
>>> a
'ThIS IS a teSt StrIng.'

5 Stimmen

Das funktioniert so lange, wie Sie keinen Ersatzstreitfall haben. Wenn Sie ersetzt haben i avec s würden Sie ein merkwürdiges Verhalten zeigen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X