【问题标题】:Folding case to speed up comparisons折叠箱加快比较
【发布时间】:2018-04-05 20:01:59
【问题描述】:
"strasse".Equals("STRAße",StringComparison.InvariantCultureIgnoreCase)

这返回真。哪个是对的。不幸的是,当我将其中一个存储在 postgres 中时,它认为在进行不区分大小写的匹配时它们是不一样的(例如,使用~*)。我也用 citext 测试过。

因此,一种解决方案是预先折叠案例,从而将这些值中的任何一个的strasse 存储在另一列中。然后我可以索引并搜索匹配项。

我一直在寻找如何在 C# 中折叠大小写,但一直无法在 C# 中找到解决方案。显然,知识是存在的,因为它可以正确比较这些字符串,我只是找不到从哪里得到它。

一种解决方案是生成一个 perl 进程perl -E "binmode STDOUT, ':utf8'; binmode STDIN, ':utf8'; while (<>) { print fc }",将这些管道的 C# 端也设置为 utf8,然后通过 perl 发送文本以折叠外壳。但是必须有比这更好的方法。

【问题讨论】:

  • 图书馆 UnidecodeSharp 可能对此有所帮助。
  • 啊,排序规则的不同实现的好老诅咒:-)
  • string.Equals(str1,str2,StringComparison.CurrentCulture) 呢?

标签: c# case-folding


【解决方案1】:

string.Normalize(),它接受NormalizationForm 参数。迈克尔卡普兰goes into detail对此。他声称它比FoldStringW做得更好。

但是,它不会将大小写规范化为大写或小写,它只会折叠为规范形式。我建议你之后申请ToUpperToLower

【讨论】:

  • 最初的目的是规范化大小写,尽管通过组合字符来规范化 unicode 的其余部分,并且所有这些都可能在以后的匹配中发挥作用。
  • 当我说“规范化大小写”时,我专门指的是大写或小写,而不是折叠成规范形式,这也是问题的一部分。
  • ToUpper / ToLower 不适用于所有语言中不区分大小写的匹配,这是问题的一部分。
  • 即使在string.Normalize之后?
  • 你用上面的字符串试过了吗?我只是将它推过 net core 3.1,不出所料,它并没有满足要求。
【解决方案2】:

查看源代码后,我最终发现这个实现的大部分都在一组名为 CompareInfo 的类中。

你可以在github.com/dotnet/runtime找到这些

这使我进入了这个页面,该页面提供了 .net 文化内容的内部运作线索。 .NET globalization and ICU

似乎 dotnet 实际上完全依赖原生库来完成除序数操作之外的所有操作。

我会由此假设 .Net Framework 可能正在使用来自 Win32 的 NLS。为此,FoldStringW 方法看起来很有前途。

对于 ICU,有 Case Mappings 的文档,我找到了 u_strFoldCase 方法。

【讨论】:

    猜你喜欢
    • 2010-10-25
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    • 2018-03-02
    相关资源
    最近更新 更多