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

dan*_*dee 6 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. Gros,groß等比赛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...
Run Code Online (Sandbox Code Playgroud)

我已经浏览了ICU变换用户指南,但没有过多投入......因为我认为这是显而易见的原因.

我知道我可以通过转换为大写然后再转换为小写来捕获case(2),这可以在这个特定应用程序的领域内工作.但是,我有兴趣在更基础的层面上解决这个问题,希望同样允许区分大小写的应用程序.

任何提示将不胜感激!

tc.*_*tc. 6

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

首先,NamesList.txtCaseFolding.txt是这类事情不可或缺的资源,如果您还没有看过它们.

部分问题是你正在尝试做一些几乎正确的事情,它适用于你关心的所有语言/语言环境,而Unicode更关心的是在单一语言环境中显示字符串时做正确的事情.

对于(2),从我可以找到的最早的CaseFolding.txt(3.0-Update1/CaseFolding-2.txt)ß开始规范大小写.并且应该做正确的事情,但如果没有,"独立于语言环境" 似乎为所有输入提供合理的答案(并且还处理臭名昭着的"土耳其语I").ssCFStringFold()-[NSString stringByFoldingWithOptions:]s.upper().lower()

对于(5),你有点不走运:Unicode 6.2似乎没有包含从Æ到AE的规范映射,并且从"字母"变为"连字"并再次返回(U + 00C6 LATIN CAPITAL LETTER A E在1.0中) ,LATIN CAPITAL LIGATURE AE在1.1和LATIN CAPITAL LETTER AE2.0).您可以在NamesList.txt中搜索"ligature"并添加一堆特殊情况.

笔记:

  • CFStringNormalize()不做你想做的事.您确实希望在将字符串添加到索引之前对其进行规范化; 我建议在其他处理的开始和结束时使用NFKC.
  • CFStringTransform()你也不想做你想做的事; 所有脚本都是"拉丁语"
  • CFStringFold()依赖于顺序:组合ypogegrammeni和prosgegrammeni被剥离,kCFCompareDiacriticInsensitive但转换为小写的iota kCFCompareCaseInsensitive."正确"的事情似乎是首先进行案例折叠,其次是其他案件,尽管剥离它可能在语言上更有意义.
  • 您几乎肯定不想使用,kCFCompareLocalized除非您希望每次语言环境更改时重建搜索索引.

其他语言的读者注意: 检查您使用的功能是否与用户当前的语言环境无关!Java用户应该使用s.toUpperCase(Locale.ENGLISH).NET用户应该使用的东西s.ToUpperInvariant().如果您确实需要用户的当前区域设置,请明确指定它.