multiple replacements in a string

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

Hallo,

Ich möchte aus einem String verschiedene genau vorher definierte Zeichen ersetzen.

Für mich der einfachste Weg :

Code: Alles auswählen

text = 'Sydney(AUS) -  Rio  de Janeiro(Bra) - Madryt/Spain   - AUS -   Monteral/CAN(CAN) - Lion(FRA)'

temp = text.replace('(AUS)', '')
temp = temp.replace('(Bra)', '')
temp = temp.replace('(CAN)', '')
temp = temp.replace('(FRA)', '')
temp = temp.replace('/Spain', '')
temp = temp.replace('/CAN', '')
temp = temp.replace('AUS', '')
temp = temp.replace('Lion', 'Lyon')
temp = temp.replace('Madryt', 'Madrid')

temp = ' '.join(temp.split())

temp = temp.replace('- -', '-')

print '=> replace()          : {}'.format(temp)
# [OUT] => replace()          : Sydney - Rio de Janeiro - Madrid - Monteral - Lyon
Dieser Weg funktioniert.

Aber wie mach ich das, wenn ich, sagen wir einmal 100.000 mögliche replacements habe ?
100.000x replace( ... ) untereinander schreiben ???

Ein möglicher Lösungsansatz ist für mich gewesen :

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf8 -*-
#
import re

class Multiple_Replaces(object):
    def __init__(self):
        # http://stackoverflow.com/questions/6116978/python-replace-multiple-strings
        replacements = { '(AUS)'  : '',
                         '(Bra)'  : '',
                         '(CAN)'  : '',
                         '(FRA)'  : '',
                         '/CAN'   : '',
                         'Lion'   : 'Lyon',
                         '/Spain' : '',
                         'Madryt' : 'Madrid' }

        self.decode  = dict((re.escape(k), v) for k, v in replacements.iteritems())
        self.pattern = re.compile("|".join(self.decode.keys()))

    def text(self, text):
        return self.pattern.sub(lambda m: self.decode[re.escape(m.group(0))], text)

mr   = Multiple_Replaces()
text = 'Sydney(AUS) -  Rio  de Janeiro(Bra) - Madryt/Spain   - AUS -   Monteral/CAN(CAN) - Lion(FRA)'

temp = mr.text(' '.join(text.split()))

print '=> Multiple_Replace() : {}'.format(temp)
# [OUT]=> Multiple_Replace() : Sydney - Rio de Janeiro - Madrid - AUS - Monteral - Lyon
Soweit so gut, aber :

Code: Alles auswählen

gewünschtes Ergebnis  : Sydney - Rio de Janeiro - Madrid - Monteral - Lyon
hin bekommen habe ich : Sydney - Rio de Janeiro - Madrid - AUS - Monteral - Lyon
Das AUS zwischen Madrid und Monteral muss aber auch noch weg.

Da ich keine Reinfolge bei den Keys in replacements vorgeben kann, kollidieren der Key 'AUS' mit dem Key '(AUS).
So wird aus (AUS) nicht etwas '', sondern (). Nicht immer, aber hin und wieder.

Zur Zeit sehe ich nur die Möglichkeit, mit mehren replacements dictionaries zu arbeiten, um eine vorgegebene Reihenfolge
einhalten zu können.

Hat jemand eine bessere Idee ?
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@Daikoku: da die Liste doch eine gewisse Regelmäßigkeit hat, wäre es da nicht besser, das bekannte Muster zu parsen und danach gewisse Elemente zu filtern:

Code: Alles auswählen

EXCLUDE = ('', 'AUS')
cities = [c for c in re.split('(?:/\S+|\(\S+\))?(?:\s+-\s+|\s*$)', text) if c not in EXCLUDE]
print ' - '.join(cities)
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

@Sirius3 Grundsätzlich kann ich bekannte Muster mit Deiner Methode natürlich eliminieren.
Aber was ist dann zum Beispiel mit Madryt -> Madrid und Lion -> Lyon ?
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@Daikoku: dabei hilft eine Übersetzungstabelle:

Code: Alles auswählen

EXCLUDE = ('', 'AUS')
TRANSLATE = {'Madryt': 'Madrid', 'Lion': 'Lyon' }
cities = [TRANSLATE.get(c, c) for c in re.split('(?:/\S+|\(\S+\))?(?:\s+-\s+|\s*$)', text) if c not in EXCLUDE]
print ' - '.join(cities)
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

@Sirius3 Vielen Dank für Deine Hilfestellungen. Ich muss ein wenig mit Deinem Code experimentieren und noch etwas in der Dokumentation zum Modul re nachlesen. Ich werde mich dann wieder melden. Vielen Dank erst einmal.
Antworten