SnTT: Kölner Phonetik - das bessere Soundex?!

von Thomas Bahn,
assono GmbH, Standort Kiel,

"Die Kölner Phonetik (auch Kölner Verfahren) ist ein phonetischer Algorithmus, der Wörtern nach ihrem Sprachklang eine Zeichenfolge zuordnet, den phonetischen Code. Ziel dieses Verfahrens ist es, gleich klingenden Wörtern den selben Code zuzuordnen, um bei Suchfunktionen eine Ähnlichkeitssuche zu implementieren. Damit ist es beispielsweise möglich, in einer Namensliste Einträge wie "Meier" auch unter anderen Schreibweisen, wie "Maier", "Mayer" oder "Mayr", zu finden. Die Kölner Phonetik ist, im Vergleich zum bekannteren Russell-Soundex-Verfahren, besser auf die deutsche Sprache abgestimmt. Sie wurde 1969 von Postel veröffentlicht." (Wikipedia, http://de.wikipedia.org/wiki/K%C3%B6lner_Phonetik)

@Soundex ist bereits in der Formelsprache vorhanden und wird zum Beispiel im Domino-Verzeichnis benutzt, um ähnlich klingende Namen zu finden (siehe erste Spalte in der ($Users)-Ansicht). Leider "funktioniert" der Soundex im Deutschen nicht so gut, wie z. B. im Englischen. Wir sprechen halt die Buchstaben etwas anders aus. Deswegen hat Herr Postel auch ein für das Deutsche besser passendes Verfahren entwickelt: die Kölner Phonetik.

Auf den ersten Blick sieht die Umsetzung noch recht einfach aus, der Teufel steckt aber im Detail. Ich bin daher froh, dass ich zumindest als Ausgangspunkt eine Implementierung des Verfahrens mit Visual Basic im vb@rchiv gefunden habe.

Die Umsetzung nach LotusScript ist trivial, da zumindest in der Implementation des Algorithmus selbst keine VB-Spezialitäten verwendet wurden.

Praktischer wäre natürlich eine Implementierung in Formelsprache, die man für berechnete Felder oder in Spaltenformel nutzen könnte. Naja, da es keine Funktionen in der Formelsprache gibt, ist die Formel etwas länger geraten, dafür punktet sie bei Listen und Listenoperationen:

_input := @Prompt([OkCancelEdit]; "Kölner Phonetik"; "Suchname eingeben"; "");

_trimmed := @Trim(_input);
_lower := @LowerCase(_trimmed);
_replacedSpecialChars := @ReplaceSubstring(_lower;
        "ph" : "ä" : "ö" : "ü" : "ß"; "f" : "a" : "o" : "u" : "ss");
_withMarkers := "#" + _replacedSpecialChars + "#";

_convertedToNumber := "";
@For(_position := 1; _position < @Length(_withMarkers) - 1; _position := _position + 1; @Do(
    _previous := @Middle(_withMarkers; _position - 1; 1);
    _current := @Middle(_withMarkers; _position; 1);
    _next := @Middle(_withMarkers; _position + 1; 1);

    _convertedToNumber := _convertedToNumber + @If(
        _position = 1;
        @If(
            (_current = "a" : "e" : "i" : "j" : "y" : "o" : "u"); "0";
            (_current = "c") & (_next = "a" : "o" : "u" : "h" : "k" : "x" :"q" : "l" : "r"); "4";
            (_current = "d" : "t") & (_next = "s" : "c" : "z"); "8";
            (_previous = "c" : "k" : "q") & _current = "x"; "8";
            (_current = "x"); "48";
            (_previous = "s") & (_current = "c" : "z"); "8";
            (_current = "h"); "-";
            (_current = "b" : "p"); "1";
            (_current = "d" : "t"); "2";
            (_current = "f" : "v" : "w"); "3";
            (_current = "g" : "k" : "q"); "4";
            (_current = "l"); "5";
            (_current = "m" : "n"); "6";
            (_current = "r"); "7";
            (_current = "c" : "s" : "z"); "8";
            "?"
        );
        @If(
            (_current = "d" : "t") & (_next = "s" : "c" : "z"); "8";
            (_previous = "c" : "k" : "q") & _current = "x"; "8";
            (_current = "x"); "48";
            (_previous = "s") & (_current = "c" : "z"); "8";
            (_current = "c") & (_next = "a" : "o" : "u" : "h" : "k" : "x" :"q"); "4";
            (_current = "h"); "-";
            (_current = "a" : "e" : "i" : "j" : "y" : "o" : "u"); "0";
            (_current = "b" : "p"); "1";
            (_current = "d" : "t"); "2";
            (_current = "f" : "v" : "w"); "3";
            (_current = "g" : "k" : "q"); "4";
            (_current = "l"); "5";
            (_current = "m" : "n"); "6";
            (_current = "r"); "7";
            (_current = "c" : "s" : "z"); "8";
            "?"
        )
    )
));

_withoutH := @ReplaceSubstring(_convertedToNumber; "-"; "");

_zerosRemoved := @If(
    @Begins(_withoutH; "0");
    "0" + @ReplaceSubstring(_withoutH; "0"; "");
    @ReplaceSubstring(_withoutH; "0"; "")
);

_dublicatesRemoved := @Left(_zerosRemoved; 1);
@For(_position := 2; _position <= @Length(_zerosRemoved); _position := _position + 1;
    _dublicatesRemoved := _dublicatesRemoved + @ReplaceSubstring(
        @Middle(_zerosRemoved; _position - 1; 1); @Right(_dublicatesRemoved; 1); ""
    )
);

@Prompt([OK]; "Kölner Phonetik"; _input + " converts to " + _dublicatesRemoved)

Fachbeitrag IBM Notes IBM Notes Traveler Tipp Entwicklung

Sie haben Fragen zu diesem Artikel? Kontaktieren Sie uns gerne: blog@assono.de

Sie wollen eine individuelle Lösung? Kontaktieren Sie uns

Weitere interessante Artikel

Sie haben Fragen? Wir sind für Sie da.

Wir verwenden Ihre Daten, um Sie einmalig per E-Mail zu kontaktieren. Wir geben Ihre Daten nicht an Dritte weiter. Siehe: Datenschutzhinweise
assono GmbH

Standort Kiel (Zentrale)
assono GmbH
Lise-Meitner-Straße 1–7
24223 Schwentinental

Standort Hamburg
assono GmbH
Bornkampsweg 58
22761 Hamburg

Telefonnummern:
Zentrale: +49 4307 900 407
Techn. Hotline: +49 4307 900 403
Vertrieb: +49 4307 900 402

E-Mail-Adressen:
kontakt@assono.de
bewerbung@assono.de