我正在编写一个帮助器,对输入字符串执行大量转换,以便创建该字符串的搜索友好表示。
考虑以下情况:
Müller
Großmann
Çingletòn
Bjørk
Æreogramme
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 User Guide for Transforms,但没有过多投入......因为我认为这是显而易见的原因。
我知道我可以通过转换为大写然后再转换为小写来捕获case(2),这可以在这个特定应用程序的领域内工作。但是,我有兴趣在更基础的层面上解决这个问题,希望同样允许区分大小写的应用程序。
任何提示都将不胜感激!
答案 0 :(得分:6)
恭喜你,你发现了一些比较痛苦的文本处理过程!
首先,NamesList.txt和CaseFolding.txt是这类事情不可或缺的资源,如果您还没有看过它们。
问题的一部分是你正在尝试做一些几乎正确的东西,它适用于你关心的所有语言/语言环境,而Unicode则更关心在显示字符串时做正确的事情单一语言区域。
对于(2),ß
已经规范地折叠为ss
,因为我可以找到最早的CaseFolding.txt(3.0-Update1/CaseFolding-2.txt)。 CFStringFold()
和-[NSString stringByFoldingWithOptions:]
应该做正确的事,但如果没有,“与语言环境无关的”s.upper().lower()
似乎可以为所有输入提供合理的答案(并且还处理臭名昭着的“土耳其语” I“)。
对于(5),你有点不走运:Unicode 6.2似乎没有包含从Æ到AE的规范映射,并且从“字母”变为“连字”并再次返回(U + 00C6)在1.0中为LATIN CAPITAL LETTER A E
,在1.1中为LATIN CAPITAL LIGATURE AE
,在2.0中为LATIN CAPITAL LETTER AE
。您可以在NamesList.txt中搜索“ligature”并添加一些特殊情况。
注意:
CFStringNormalize()
没有做你想做的事。你做想要在将字符串添加到索引之前对其进行规范化;我建议在其他处理的开始和结束时使用NFKC。CFStringTransform()
也不是你想要的;所有脚本都是“拉丁语”CFStringFold()
与订单相关:合并ypogegrammeni and prosgegrammeni被kCFCompareDiacriticInsensitive
剥离,但由kCFCompareCaseInsensitive
转换为小写iota。 “正确”的事情似乎是首先进行案例折叠,然后是其他案例,尽管剥离它可能在语言上更有意义。kCFCompareLocalized
。 来自其他语言的读者注意:检查您使用的功能不取决于用户当前的区域设置! Java用户应该使用s.toUpperCase(Locale.ENGLISH)
之类的东西,.NET用户应该使用s.ToUpperInvariant()
。如果您确实需要用户的当前区域设置,请明确指定它。
答案 1 :(得分:0)
我在String上使用了以下扩展程序,它似乎运行良好。
f