15

如果我执行以下语句:

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 'Where' 方法,但现在我必须使用另一个人编写的这个自定义函数,因为他说它性能更好。

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

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


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

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

4

3 回答 3

23

有一个平局算法在工作,请参阅http://unicode.org/reports/tr10/

为了解决语言敏感排序的复杂性,采用了多级比较算法。例如,在比较两个单词时,最重要的特征是基本字符:例如 A 和 B 之间的差异。如果基本字母有任何差异,则通常会忽略重音差异。如果基数或重音有任何差异,则通常会忽略大小写差异(大写与小写)。标点是可变的。在某些情况下,标点符号被视为基本字符。在其他情况下,如果有任何基数、重音或大小写差异,则应忽略它。也可能有一个最终的打破平局的级别,如果字符串中根本没有其他差异,则使用(规范化的)代码点顺序。

So, "Munt..." and "Münc..." are alphabetically different and sort based on the "t" and "c".

Whereas, "mun" and "mün" are alphabetically the same ("u" equivelent to "ü" in lost languages) so the character codes are compared

于 2009-09-03T07:26:04.550 回答
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 规则是正确的——但我对它们知之甚少。

至于您是否需要考虑到这一点……我不希望如此。你在做什么被这个抛出?

于 2009-09-03T07:21:10.243 回答
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);

给出了想要的结果。

无论如何,我认为您最好将排序基于特定文化,例如当前用户的文化(如果可能)。

于 2009-09-03T07:21:16.700 回答