Seite 1 von 1
Synonyme
Verfasst: Mittwoch 10. April 2019, 21:50
von new2python
Hallo zusammen,
ich möchte folgendes tun:
in mehreren deutschen Text-Dateien möchte ich (mit Regular Expressions?) nach unterschiedlichen Schreibweisen für den gleichen Begriff suchen und wenn ich es finde, immer mit dem gleichen Begriff ersetzen. Zum Beispiel
"Str." oder "Strasse" oder "Straße" möchte ich immer als "Straße" erkennen und ersetzen
Das möchte ich mit 4 Begriffen tun und ich kenne für alle schon unterschiedliche Schreibweisen, die in den Dokumenten vorkommen und Synonyme.
Könnt ihr mir helfen? Ich bin ein absoluter Python-Einsteiger.
Danke!!!
Re: Synonyme
Verfasst: Mittwoch 10. April 2019, 23:39
von __blackjack__
@new2python: In der Python-Dokumentation findest Du ein Tutorial für die Python-Grundlagen und ein Howto für reguläre Ausdrücke.
Re: Synonyme
Verfasst: Donnerstag 11. April 2019, 03:09
von snafu
@new2python: Strings haben eine
replace()-Methode. Damit kannst du Ersetzungen vornehmen. Ein erster Ansatz wäre also:
Code: Alles auswählen
text.replace('Str.', 'Straße').replace('Strasse', 'Straße')
Das ist allerdings nicht besonders effizient, wenn man es mit umfangreichen Texten und vielen zu tätigen Ersetzungen zu tun hat. Dann sollte man sich das
re-Modul und hier inbesondere
re.sub() anschauen, um reguläre Ausdrücke zum Finden und Ersetzen anzuwenden. Würde dann so aussehen:
Etwas fortgeschrittener lässt sich dafür auch eine Funktion schreiben. Hier mal als lauffähiges Skript:
Code: Alles auswählen
import re
EXAMPLE = 'In der Str. ist eine Straße oder Strasse'
def replace(text, needles, replacement):
pattern = '|'.join(map(re.escape, needles))
return re.sub(pattern, replacement, text)
def main():
replaced = replace(EXAMPLE, ['Str.', 'Strasse'], 'Straße')
print(replaced)
if __name__ == '__main__':
main()
Re: Synonyme
Verfasst: Donnerstag 11. April 2019, 04:14
von snafu
Der Ansatz mit regulären Ausdrücken lässt sich übrigens weiter ausbauen, wenn man unterschiedliche Ersetzungen vornehmen möchte. Ich habe das hier mal als Klasse implementiert, wäre aber auch als Funktion mit entsprechendem Wörterbuch denkbar. Ich fand es mit der
add_rule()-Methode jedoch anwenderfreundlicher.
Code: Alles auswählen
import re
EXAMPLE = """
Bernd Meier, Kurze Str. 42, Tel.: 12345
Lisa Müller, Lange Strasse 77, Tel.-Nr.: 67890
Hans Wurst, Hauptstraße 11, Telefon: 54745
"""
class Translator:
def __init__(self):
self.replacements = {}
def add_rule(self, needles, replacement):
for needle in needles:
self.replacements[needle] = replacement
def _replace(self, match):
needle = match.group()
return self.replacements[needle]
def translate(self, text):
# NOTE: "|" is always non-greedy!
# -> take long needles first to avoid false positives
size_sorted = sorted(self.replacements, key=len, reverse=True)
pattern = '|'.join(map(re.escape, size_sorted))
return re.sub(pattern, self._replace, text)
def main():
trans = Translator()
trans.add_rule(['Str.', 'Strasse'], 'Straße')
trans.add_rule(['Tel.', 'Tel.-Nr.', 'Telefon'], 'Telefonnummer')
print(trans.translate(EXAMPLE))
if __name__ == '__main__':
main()
Re: Synonyme
Verfasst: Donnerstag 11. April 2019, 06:10
von snafu
Bei
sorted() habe ich zu kompliziert gedacht. Es reicht, einfach rückwärts zu sortieren, ohne speziellem
key. Im Hinblick darauf, dass die Regex-Engine als "dummer" endlicher Automat implementiert ist, dürfte das sogar etwas schneller laufen, da gleiche Wortanfänge unmittelbar aufeinander folgen (habe aber nicht nachgemessen).
Code: Alles auswählen
import re
EXAMPLE = """\
Bernd Meier, Kurze Str. 42, Tel.: 12345
Lisa Müller, Lange Strasse 77, Tel.-Nr.: 67890
Hans Wurst, Hauptstraße 11, Telefon: 54745"""
class Translator:
def __init__(self):
self.replacements = {}
def add_rule(self, needles, replacement):
for needle in needles:
self.replacements[needle] = replacement
def _replace(self, match):
needle = match.group()
return self.replacements[needle]
def translate(self, text):
replacements = sorted(self.replacements, reverse=True)
pattern = '|'.join(map(re.escape, replacements))
return re.sub(pattern, self._replace, text)
def main():
trans = Translator()
trans.add_rule(['Str.', 'Strasse'], 'Straße')
trans.add_rule(['Tel.', 'Tel.-Nr.', 'Telefon'], 'Telefonnummer')
print(trans.translate(EXAMPLE))
if __name__ == '__main__':
main()
Re: Synonyme
Verfasst: Donnerstag 11. April 2019, 07:12
von new2python
Danke!!!!
Re: Synonyme
Verfasst: Freitag 12. April 2019, 17:21
von snafu
Fun Fact: Der simple Ansatz über die wiederholte Anwendung von
text.replace() ist auch bei längeren Texten deutlich schneller als der Weg über die Regex-Engine. Folglich ist es in dieser Form flotter:
Code: Alles auswählen
EXAMPLE = """\
Bernd Meier, Kurze Str. 42, Tel.: 12345
Lisa Müller, Lange Strasse 77, Tel.-Nr.: 67890
Hans Wurst, Hauptstraße 11, Telefon: 54745"""
class Translator:
def __init__(self):
self.replacements = {}
def add_rule(self, needles, replacement):
for needle in needles:
self.replacements[needle] = replacement
def translate(self, text):
for needle in sorted(self.replacements, reverse=True):
text = text.replace(needle, self.replacements[needle])
return text
def main():
trans = Translator()
trans.add_rule(['Str.', 'Strasse'], 'Straße')
trans.add_rule(['Tel.', 'Tel.-Nr.', 'Telefon'], 'Telefonnummer')
print(trans.translate(EXAMPLE))
if __name__ == '__main__':
main()