Benötigt Character.isLetter normalisierten Text?

9

Ich habe ein Programm, das Strings herausfiltert, indem es jedes Zeichen entfernt, das kein Buchstabe oder eine Ziffer ist. Dieses Programm unterstützt eine große Anzahl von Sprachen, darunter Chinesisch, Russisch, Arabisch, etc. Das Programm ist wie folgt:

%Vor%

Ich benutze codePointAt Methode, um Zeichen zu unterstützen, die in UTF 32 Bits über High und Low Surrogate ausgedrückt werden. Ich muss wissen, ob jeder String vor der Filterung normalisiert werden muss? Ich beziehe mich darauf, die Methode Normalizer.normalize vor dem Ausführen der Schleife aufzurufen. Wenn ja, welche Normalizer.Form soll ich verwenden?

Danke.

    
user2144762 07.03.2013, 14:57
quelle

2 Antworten

4

Es hängt alles davon ab, wie Ihr Algorithmus sich wirklich verhalten soll.

Betrachten wir als Beispiel die Zeichenkette "a\u0308" (U + 0061 ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴀ gefolgt von U + 0308 ᴄᴏᴍʙɪɴɪɴɢ ᴅɪᴀᴇʀᴇsɪs), die kanonisch äquivalent zu "ä" oder "\u00e4" (U + 00E4 ʟᴀᴛɪɴ sᴍᴀʟʟ) ist ᴅɪᴀᴇʀᴇ ᴀ ᴡɪᴛʜ ᴅɪᴀᴇʀᴇsɪs). Kanonisch äquivalent zu sein, bedeutet, dass Ihr Algorithmus nicht zwischen diesen beiden unterscheiden sollte. Eine einfache Möglichkeit, kanonisch äquivalente Strings zu erhalten, um sich gleich zu verhalten, besteht darin, die beiden auf das gleiche kanonische Normalisierungsformat zu normalisieren: entweder NFC oder NFD.

Je nachdem, was diese Zeichenfolgen darstellen, möchten Sie möglicherweise stattdessen die Kompatibilitätsäquivalenz (NFKC oder NFKD) verwenden. Dies wird allgemein beispielsweise für Kennungen empfohlen. Diese beiden konvertieren Kompatibilitätszeichen in ihre empfohlenen Äquivalente (wie U + 2126 ᴏʜᴍ sɪɢɴ nach U + 03A9 or ᴄᴀᴘɪᴛᴀʟ ʟᴇᴛᴛᴇʀ ᴏᴍᴇɢᴀ oder Ligaturzeichen mit den Zeichenfolgen, aus denen sie bestehen).

Unabhängig davon, welche Art von Äquivalenz Sie wollen, das Prinzip bleibt das gleiche: Wenn Sie äquivalente Strings gleichermaßen behandeln wollen, ist das Normalisieren beider der einfachste Weg.

Sobald Sie das gleiche Verhalten für alle äquivalenten Strings haben, müssen Sie ein anderes Problem in Betracht ziehen: Wenn Sie alle "Zeichen [s] weglassen, die [kein] Buchstabe oder eine Ziffer sind", was passiert mit Strings mit Buchstaben und Kombinationszeichen, wie "\u092C\u093F" (U + 092C ᴅᴇᴠᴀɴᴀɢᴀʀɪ ʟᴇᴛᴛᴇʀ ʙᴀ gefolgt von U + 093F ᴅᴇᴠᴀɴᴀɢᴀʀɪ ᴠᴏᴡᴇʟ sɪɢɴ ɪ, sieht aus wie बि)? Dies sind zwei separate Codepunkte und U + 093F ist kein Buchstabe. Diese beiden bilden keine Normalisierungsform. Möchten Sie, dass die Kombinationszeichen gelöscht werden (wobei Sie mit ब belassen werden) oder nicht?

Wenn Sie sie löschen können, können Sie Ihren aktuellen Algorithmus verwenden. Andernfalls möchten Sie wahrscheinlich über Graphem-Cluster iterieren, bei denen es sich grob um Sequenzen von Basiszeichen gefolgt von den Kombinationsmarken handelt. Sowohl Java als auch ICU bietet APIs zum Auffinden von Graphem-Clustern (Java nennt diese "Zeichenumbrüche").

    
R. Martinho Fernandes 07.03.2013 17:28
quelle
0

Beachten Sie, dass Ihr Code zum Iterieren der Codepunkte nicht ganz korrekt ist, ich glaube, Sie wollen:

%Vor%

Entschuldigung, ich weiß nicht, ob Sie normalisieren müssen oder nicht.

    
jtahlborn 07.03.2013 15:15
quelle

Tags und Links