我正在编写一个助手,它对输入字符串执行多次转换,以便创建该字符串的搜索友好表示。
考虑以下场景:
- 德语或法语文本全文搜索
- The entries in your datastore contain
Müller
Großmann
Çingletòn
Bjørk
Æreogramme
- The search should be fuzzy, in that
-
ull
, Üll
等等匹配Müller
-
Gros
, groß
等等匹配Großmann
-
cin
等等匹配Çingletòn
-
bjö
, bjo
等等匹配Bjørk
-
aereo
等等匹配Æreogramme
到目前为止,我已经成功解决了案例(1)、(3)和(4)。
我不明白的是如何处理(2)和(5)。
到目前为止,我已经尝试了以下方法,但没有效果:
CFStringNormalize() // with all documented normalization forms
CFStringTransform() // using the kCFStringTransformToLatin, kCFStringTransformStripCombiningMarks, kCFStringTransformStripDiacritics
CFStringFold() // using kCFCompareNonliteral, kCFCompareWidthInsensitive, kCFCompareLocalized in a number of combinations -- aside: how on earth do I normalize simply _composing_ already decomposed strings??? as soon as I pack that in, my formerly passing tests fail, as well...
我浏览过ICU 变换用户指南但并没有投入太多......出于我认为显而易见的原因。
我知道我可以通过转换为大写然后再转换回小写来捕获情况 (2),这将在这个特定应用程序的范围内工作。然而,我有兴趣在更基础的层面上解决这个问题,希望也允许区分大小写的应用程序。
任何提示将不胜感激!
恭喜,您已经发现了文本处理中最痛苦的部分之一!
首先,姓名列表.txt and 案例折叠.txt如果您还没有看过的话,它们是此类事物不可或缺的资源。
部分问题在于你正在尝试做某事几乎正确它适用于您关心的所有语言/区域设置,而 Unicode 更关心在单一语言区域设置中显示字符串时执行正确的操作。
对于(2),ß
已规范地大小写折叠为ss
自从我能找到最早的 CaseFolding.txt (3.0-Update1/CaseFolding-2.txt). CFStringFold()
and -[NSString stringByFoldingWithOptions:]
应该做正确的事情,但如果不正确,则“独立于语言环境”s.upper().lower()
似乎对所有输入给出了合理的答案(并且还处理了臭名昭著的“土耳其语 I”)。
对于 (5),你有点运气不好:Unicode 6.2 似乎不包含从 Æ 到 AE 的规范映射,并且已从“字母”更改为“连字”并再次更改回来(U+00C6 是LATIN CAPITAL LETTER A E
在1.0中,LATIN CAPITAL LIGATURE AE
在 1.1 中,以及LATIN CAPITAL LETTER AE
在 2.0 中)。您可以在 NamesList.txt 中搜索“连字”并添加一堆特殊情况。
Notes:
-
CFStringNormalize()
不做你想做的事。你do想要在将字符串添加到索引之前对其进行规范化;我建议在其他处理的开始和结束时使用 NFKC。
-
CFStringTransform()
也没有完全达到你想要的效果;所有脚本都是“拉丁文”
-
CFStringFold()
是顺序相关的:组合ypogegrammeni 和 progegrammeni被剥夺kCFCompareDiacriticInsensitive
但转换为小写iotakCFCompareCaseInsensitive
。 “正确”的做法似乎是先进行案例折叠,然后再进行其他操作,尽管剥离它可能在语言上更有意义。
- 您几乎肯定不想使用
kCFCompareLocalized
除非您想在每次区域设置更改时重建搜索索引。
其他语言的读者请注意:检查您使用的功能是否是not取决于用户当前的区域设置! Java 用户应该使用类似的东西s.toUpperCase(Locale.ENGLISH)
, .NET 用户应该使用s.ToUpperInvariant()
。如果您确实想要用户当前的区域设置,请明确指定它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)