Unicode auf ASCII abbilden

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
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Bei meinem aktuellen Spielzeug-Projekt (Offlinewörterbuch: https://github.com/cofi/pdictcc) habe ich ein kleines Problem mit Zeichen abseits von ASCII.

Was ich haben will: Wenn ich nach 'voegel' suche, will ich bei den Ergebnissen auch die Ergebnisse fuer 'vögel' sehen.

Jetzt hab ich 2 Ansaetze: Bei der Suche auf ASCII oder beim Datenimport normalisieren, wobei ich stark zu letzterem tendiere, da bei ersterem 2 Suchen faellig werden ('voegel' und 'vögel', da es auch Woerter gibt, die nach "Umlautschreibweise" aussehen, z.b. quelle), aber mit der Gefahr, dass ich unnoetig False positives generiere (die Gefahr sehe ich weniger). Wie seht ihr das?

Mein groesstes Problem ist aber, wie ich diese Abbildung machen kann. Natuerlich kann ich damit nicht den ganzen Unicode-Raum abdecken, das ist klar, dennoch denke ich, dass der Ansatz sinnvoll ist. Was ich aber nicht machen will, ist manuell eigene Codetables anzulegen.
Kennt ihr denn Sammlungen von gaengigen Abbildungsschemata (z.B 'ü' -> 'ue')? Oder habt ihr Stichwoerter fuer mich?
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Du könntest im Deutschen die Umlaute und ß auf die Umschrift normalisieren. Wenn du das mit deiner Datenbasis ebenfalls machst, kommst du mit einer Suchanfrage aus. Doch sind zwei Anfragen wirklich so schlimm? Würdest du beide Formen im Suchindex halten, ist das doch immer noch O(1).

In anderen Ländern gelten außerdem andere Vorschriften. Manchmal kann man die Sonderzeichen einfach weglassen, manchmal anders umschreiben. Es sind ja nicht nur Umlaute, sondern diverse Striche, Kreise und Tilden.

Stefan
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Waere es nur der konstante Zugriff, waeren 2 Zugriffe alles andere als ein Problem, ja ;)
Mit RegExp- und Volltext-Suchen ist man aber schon bei linearen Zugriffen, da beide einen vollen Scan durchfuehren. Wobei man hier die Queries umschreiben koennte, sodass beides gleichzeitig gesucht wird. Da muesste man dann aber auch noch die Ergebnisse durchgehen, um zu ueberpruefen, ob es schon Treffer beim Original-Query gab und wenn ja den Rest verwerfen. Das finde ich nicht so prickelnd :/

Das Problem aber wuerde da auch bestehen: Wie kann ich fuer ASCII-Suchanfragen Unicode-Ergebnisse liefern? Umschreiben wuerde ich hier im Uebrigen nur die Schluessel, nicht die eigentlichen Daten.

Genau diese anderen Vorschriften und Verfahren interessieren mich, wuerde man ā mit a-, à mit `a, å mit ao, ã a~ usw. darstellen? Oder ist gibt es hier nichts mehr oder weniger "einheitliches"?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich hab es mir jetzt einfach gemacht und es dem Nutzer ueberlassen ;)

Dabei ist das hier herausgefallen:

Code: Alles auswählen

def transform_key(key, transcriptions):
    """
    Transform the key with the given transcriptions.

    :param key: key to transform
    :type key: unicode
    :param transcriptions: maps the string to replace to the replacement
    :type transcriptions: dict
    """
    # the replacements have to happen concurrently, to prevent retranslations
    # so we build regexp to find all candidates and translate via dict lookup
    rx = re.compile(u'{0}'.format('|'.join(re.escape(k) for k in transcriptions)))
    return rx.sub(lambda m: transcriptions.get(m.group(0), ''), key)

Code: Alles auswählen

In [6]: print transform_key(u'äöü', dict([(u'ä', 'ae'), ('ae', u'ä'), (u'ö', 'oe')]))
aeoeü
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Wie ist das unter Ubuntu eigentlich gelöst, wenn als encoding iso88591 verwendet wird? Das €-Zeichen wird dann ja auch durch 'EUR' ersetzt...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wie sieht's hiermit aus?

Code: Alles auswählen

$ echo täßt | iconv -t ascii//translit
taesst
@mutella: "3€" und sowas klappt damit auch.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich dachte schon iconv's translit waere ein gangbarer Weg, aber nein:

Code: Alles auswählen

╭─ ○ <cofi@hitchhiker> ~ 
╰─ %> echo öäü | iconv -t ascii//translit
oau
Schade.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dann sind deine Einstellungen komisch (bzw wahrscheinlich "undeutsch" ^^). Bei mir klappt es wie erwartet. Was spuckt denn `echo $LANG` aus?

//edit: Obwohl, scheint damit nichts zu tun zu haben. Mit einem `LANG=C` davor habe ich die selben Ergebnisse. Dann weiß ich nicht, was bei dir das Problem ist. Sorry.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Hmm du hast da einen wichtigen Punkt getroffen: Ich laufe mit en_US Locales. Aber:

Code: Alles auswählen

╭─ ○ <cofi@hitchhiker> ~ 
╰─ %> LC_ALL=de_DE.utf8 echo öäü | iconv -t ascii//translit
oau
Ich denke das trifft auch gerade das Problem das ich damit habe: Fuer den Benutzer nicht unbedingt nachvollziehbare Ergebnisse.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Klar, dann läuft es letztlich wohl tatsächlich auf eine feste Übersetzungstabelle hinaus. Trotzdem bleibt das Gefühl (zumindest bei mir) das es doch irgendwas fertiges - und vor allem: robustes - dafür geben muss... ;)
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

cofi hat geschrieben:

Code: Alles auswählen

╭─ ○ <cofi@hitchhiker> ~ 
╰─ %> LC_ALL=de_DE.utf8 echo öäü | iconv -t ascii//translit
oau

Code: Alles auswählen

jakob:~ $ echo öäü | LANG=de_DE.utf8 iconv -t ascii//translit
oeaeue
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

nomnom hat geschrieben:
cofi hat geschrieben:

Code: Alles auswählen

╭─ ○ <cofi@hitchhiker> ~ 
╰─ %> LC_ALL=de_DE.utf8 echo öäü | iconv -t ascii//translit
oau

Code: Alles auswählen

jakob:~ $ echo öäü | LANG=de_DE.utf8 iconv -t ascii//translit
oeaeue
Aaah, jetzt macht auch `LANG=C` einen Unterschied. War meine Vermutung also doch richtig. :)

Nun ja. Man könnte der Konsistenz wegen ja einfach eine fest definierte Einstellung für `$LANG` mitgeben. Zum Beispiel als Argument einer Wrapper-Funktion, die den Befehl als Subprozess aufruft.
Antworten