为什么string.Compare似乎不一致地处理重音字符?

时间:2009-09-03 07:03:55

标签: c# sorting diacritics string-comparison

如果我执行以下声明:

string.Compare("mun", "mün", true, CultureInfo.InvariantCulture)

结果为'-1',表示'mun'的数值低于'mün'。

但是,如果我执行此声明:

string.Compare("Muntelier, Schweiz", "München, Deutschland", true, CultureInfo.InvariantCulture)

我得到'1',表示'Muntelier,Schewiz'应该排在最后。

这是比较中的错误吗?或者,更有可能的是,在排序包含重音

的字符串时,我应该考虑一个规则

这是一个问题的原因是,我正在对一个列表进行排序,然后进行手动二进制过滤,这意味着每个字符串都以“xxx”开头。

以前我使用的是Linq'Fhere'方法,但现在我必须使用另一个人编写的这个自定义函数,因为他说它表现得更好。

但是自定义函数似乎没有考虑.NET具有的“unicode”规则。因此,如果我告诉它过滤'mün',它就找不到任何项目,即使列表中的项目以'mun'开头。

这似乎是因为重音字符的排序不一致,具体取决于重音字符后面的字符。


好的,我想我已经解决了这个问题。

在过滤之前,我会根据每个字符串的第一个 n 字母进行排序,其中 n 是搜索字符串的长度。

3 个答案:

答案 0 :(得分:23)

有一项打破平局的算法,请参阅http://unicode.org/reports/tr10/

  

解决复杂问题   语言敏感的排序,a   多级比较算法是   采用。比较两个单词,for   例如,最重要的特征是   基本字符:如   A和B之间的差异   重点差异通常是   忽略,如果有任何差异   在基本字母中。案例差异   (大写与小写),是   通常被忽略,如果有的话   基础或口音的差异。   标点符号是可变的。在一些   标点符号的情况   像基本字符一样对待。在   其他情况,应该被忽略   如果有任何基础,口音或案例   差异。也可能有一个   最终,打破平局,如果   根本没有其他差异   在字符串中,(规范化的)代码   使用点顺序。

所以,“Munt ......”和“Münc......”按字母顺序不同,并根据“t”和“c”排序。

然而,“mun”和“mün”在字母上是相同的(“u”等于“ü”在丢失的语言中)所以比较字符代码

答案 1 :(得分:6)

看起来重音字符只用于某种“打破平局”的情况 - 换句话说,如果字符串相等。

以下是一些示例代码:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        Compare("mun", "mün");
        Compare("muna", "münb");
        Compare("munb", "müna");
    }

    static void Compare(string x, string y)
    {
        int result = string.Compare(x, y, true, 
                                   CultureInfo.InvariantCulture));

        Console.WriteLine("{0}; {1}; {2}", x, y, result);
    }
}

(我也试过在“n”之后添加一个空格,看它是否在单词边界上完成 - 它不是。)

结果:

mun; mün; -1
muna; münb; -1
munb; müna; 1

我怀疑各种复杂的Unicode规则是正确的 - 但我对它们知之甚少。

至于你是否需要考虑到这一点......我不希望如此。这是怎么回事?

答案 2 :(得分:4)

据我所知,它仍然有些一致。使用CultureInfo.InvariantCulture进行比较时,将变音字符ü视为非重音字符u

由于第一个示例中的字符串显然不相等,结果不会是0而是-1(这似乎是默认值)。在第二个示例中, Muntelier 是最后一个,因为 t 在字母表中跟随 c

我在MSDN中找不到任何解释这些规则的明确文档,但我找到了

string.Compare("mun", "mün", CultureInfo.InvariantCulture,  
    CompareOptions.StringSort);

string.Compare("Muntelier, Schweiz", "München, Deutschland", 
    CultureInfo.InvariantCulture, CompareOptions.StringSort);

给出了期望的结果。

无论如何,我认为你最好根据当前用户的文化(如果可能的话)对特定文化进行排序。