折叠/标准化连接(例如Æ到ae)使用(核心)基础

时间:2012-02-21 11:18:30

标签: unicode transform core-foundation foundation

我正在编写一个帮助器,对输入字符串执行大量转换,以便创建该字符串的搜索友好表示。

考虑以下情况:

  • 全文搜索德语或法语文本
  • 数据存储区中的条目包含
    1. Müller
    2. Großmann
    3. Çingletòn
    4. Bjørk
    5. Æreogramme
  • 搜索应该是模糊的
    1. ullÜll等匹配Müller
    2. Grosgroß等匹配Großmann
    3. cin等匹配Çingletòn
    4. bjöbjo等匹配Bjørk
    5. 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),这可以在这个特定应用程序的领域内工作。但是,我有兴趣在更基础的层面上解决这个问题,希望同样允许区分大小写的应用程序。

任何提示都将不胜感激!

2 个答案:

答案 0 :(得分:6)

恭喜你,你发现了一些比较痛苦的文本处理过程!

首先,NamesList.txtCaseFolding.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 prosgegrammenikCFCompareDiacriticInsensitive剥离,但由kCFCompareCaseInsensitive转换为小写iota。 “正确”的事情似乎是首先进行案例折叠,然后是其他案例,尽管剥离它可能在语言上更有意义。
  • 除非您希望每次语言环境发生变化时重建搜索索引,否则几乎肯定不想使用kCFCompareLocalized

来自其他语言的读者注意:检查您使用的功能取决于用户当前的区域设置! Java用户应该使用s.toUpperCase(Locale.ENGLISH)之类的东西,.NET用户应该使用s.ToUpperInvariant()。如果您确实需要用户的当前区域设置,请明确指定它。

答案 1 :(得分:0)

我在String上使用了以下扩展程序,它似乎运行良好。

f