Einmal translate() statt mehrmals replace()

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Habe mich mal intensiver mit str.translate() beschäftigt. Im Forum sehe ich dessen Nutzung recht selten, eigentlich fällt mir gerade gar kein Fall ein. Daher verliere ich nun ein paar Worte dazu.

Häufig hat man ja das Problem, dass mehrere Ersetzungen in Texten gemacht werden müssen. Da replace() immer nur eine Art von Ersetzung vornehmen kann (alle X durch Y), behilft man sich mit einer Aneinanderreihung von replace()-Aufrufen. Sagen wir mal, es sollen alle "X", "Y" und "Z" gelöscht werden. Das sähe mit replace() dann so aus:

Code: Alles auswählen

text = 'fhgfdhgXghsgkhXYsgskgZZZhsfgfgYYshfsZXZkfghXYZfhg'
clean_text = text.replace('X', '').replace('Y', '').replace('Z', '')
Unschön zu schreiben und auch mit ungünstiger Laufzeit, da jeder replace()-Aufruf wieder den kompletten Text durchlaufen muss.

Hier kommt nun translate() ins Spiel: Es nimmt für die Übersetzung ein Mapping (z.B. Wörterbuch). Wichtig ist, dass die Schlüssel Ordinals sein müssen, also der "Zahlwert" eines Zeichens. Die Werte können ebenfalls Ordinals sein oder normaler Text (wie bei replace()) oder None, wenn das Zeichen gelöscht werden soll. Hier also obiges Beispiel mit translate():

Code: Alles auswählen

text = 'fhgfdhgXghsgkhXYsgskgZZZhsfgfgYYshfsZXZkfghXYZfhg'
table = dict.fromkeys(map(ord, 'XYZ'))
clean_text = text.translate(table)
translate() geht hierbei in einem Rutsch die infrage kommenden Ersetzungen durch. Ein mehrfaches Durchlaufen des Textes wird also vermieden.

Zugegeben, der Aufbau der Übersetzungstabelle wirkt etwas lowlevel, aber das lässt sich natürlich in eine Funktion auslagern, wenn man möchte.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Gut zu wissen, Danke.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und wenn einem das mit dem Ordinals mappen zu nervig ist, dann kann man auch zu maketrans() greifen. Obige Übersetzungstabelle erhält man so:

Code: Alles auswählen

table = str.maketrans(dict.fromkeys('XYZ'))
Sicherlich möchte man nicht nur Zeichen löschen, sondern auch ersetzen. Hier finde ich maketrans() auf jeden Fall einfacher in der Handhabung. Ein Beispiel:

Code: Alles auswählen

text = 'gsgfgsShhgrgrSgrhgHsgrghrHsgrshkkEkkbbSuubklkbHkbuu'
table = str.maketrans({'S': 'Spam', 'H': 'Ham', 'E': 'Eggs'})
spammed_text = text.translate(table)
Antworten