"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)