全球化(5):排序和字符串比较
在全球化的需求中,不同区域的用户可能对“排序”列表有完全不同德期望。不同语言之间不仅字母顺序不同,而且字典和电话簿中的项目排序约定也可能大相径庭。例如,在瑞典语中,一些带重音符号的元音排在 "Z" 之后,而在其他一些欧洲国家/地区中,同样带有重音符号的元音却紧跟在不带音调符号的元音之后。包括非拉丁语脚本字符的语言具有一些特殊的排序规则。亚洲语言可按拼音、部首顺序、笔画数等多种方式进行排序。字符串的排序和比较是特定于语言的。即使在基于拉丁语脚本的语言中,也有不同的构成和排序规则。因此,在进行排序和字符串比较时,依靠的并不是码点。
.NET中的字符串比较
CompareInfo类提供了一组可用来执行区分文化的字符串比较方法。CultureInfo.CompareInfo属性CultureInfo 类的一个实例)可定义如何针对特定文化来比较和排序字符串。String.Compare方法使用CultureInfo.CompareInfo 属性中的信息来比较字符串。如果 string1 小于 string2,此方法返回一个负整数;如果 string1 和 string2 相等,则返回零 (0);如果 string1 大于 string2,则返回一个正整数。
1: using System;
2: using System.Globalization;
3: using System.Threading;
4:
5: class Program
6: {
7: static void Main(string[] args)
8: {
9: string str1 = "Apple";
10: string str2 = "Æble";
11:
12: Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
13: Console.WriteLine(String.Compare(str1, str2));
14:
15: Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
16: Console.WriteLine(String.Compare(str1, str2));
17:
18: Console.ReadLine();
19: }
20: }
21:
以上代码示例将说明如何根据进行比较时所使用的文化,通过 String.Compare 方法以不同的方式来计算两个字符串。首先,将 CurrentCulture 设置为丹麦语(丹麦),并比较字符串 "Apple" 和 "Æble"。丹麦语将字符 "Æ" 视为一个单独的字母,在字母表中将其排在 "Z" 之后。因此对于丹麦语文化,字符串 "Æble" 大于 "Apple"。接下来,将 CurrentCulture 设置为英语(美国),再次比较字符串 "Apple" 和 "Æble"。这一次,字符串 "Æble" 被认为小于 "Apple"。英语语言将字符 "Æ" 视为一个特殊符号,在字母表中将其排在字母 "A" 之前。
运行结果:
替代字符串排序
一些文化可支持多种排序顺序。例如,文化 "zh-CN"(中国中文)支持按发音(默认)和按笔画数排序。使用文化名称(如 "zh-CN")创建 CultureInfo 对象时,将使用默认排序顺序。要指定替代排序顺序,请使用替代排序顺序的 LCID 创建一个 CultureInfo 对象。然后,从 CultureInfo.CompareInf 获取一个 CompareInfo 对象以用于字符串比较。或者,也可以使用 CompareInfo.GetCompareInfo 方法 (Int32) 并指定替代排序顺序的 LCID 来直接创建一个 CompareInfo 对象。
支持替代排序顺序的文化以及用于默认和替代排序顺序的 LCID:
区域性名称 | 语言 - 国家/地区 | 默认排序名称和 LCID | 替换排序名称和 LCID |
---|---|---|---|
es-ES |
西班牙语 - 西班牙 |
国际:0x00000C0A |
传统:0x0000040A |
zh-TW |
中文 - 台湾 |
笔画数:0x00000404 |
注音符号:0x00030404 |
zh-CN |
中文 - 中国 |
发音:0x00000804 |
笔画数:0x00020804 |
zh-HK |
中文 - 香港特别行政区 |
笔画数:0x00000c04 |
笔画数:0x00020c04 |
zh-SG |
中文 - 新加坡 |
发音:0x00001004 |
笔画数:0x00021004 |
zh-MO |
中文 - 澳门特别行政区 |
发音:0x00001404 |
笔画数:0x00021404 |
ja-JP |
日语 - 日本 |
默认:0x00000411 |
Unicode:0x00010411 |
ko-KR |
朝鲜语 - 韩国 |
默认:0x00000412 |
朝鲜语 Xwansung - Unicode:0x00010412 |
de-DE |
德语 - 德国 |
词典:0x00000407 |
电话簿排序 DIN:0x00010407 |
hu-HU |
匈牙利语 - 匈牙利 |
默认:0x0000040e |
技术排序:0x0001040e |
ka-GE |
格鲁吉亚语 - 格鲁吉亚 |
传统:0x00000437 |
现代排序:0x00010437 |
中文默认拼音排序:
1: using System;
2: using System.Globalization;
3: using System.Threading;
4: using System.Collections;
5: using System.Collections.Generic;
6:
7: class Program
8: {
9: static void Main(string[] args)
10: {
11: //默认拼音LCID:0x00000804
12: Thread.CurrentThread.CurrentCulture = new CultureInfo(2052);
13: SortedList<string,string> MyList = new SortedList<string,string>();
14: MyList.Add("一(yi)", "data1");
15: MyList.Add("二(er)", "data2");
16: MyList.Add("三(san)", "data3");
17:
18: foreach(KeyValuePair<string, string> kvp in MyList )
19: {
20: Console.WriteLine("{0} is {1}", kvp.Key, kvp.Value);
21: }
22:
23: Console.ReadLine();
24: }
25: }
26:
27:
结果:
中文笔画排序:
1: using System;
2: using System.Globalization;
3: using System.Threading;
4: using System.Collections;
5: using System.Collections.Generic;
6:
7: class Program
8: {
9: static void Main(string[] args)
10: {
11: //笔画排序LCID:0x00020804
12: Thread.CurrentThread.CurrentCulture = new CultureInfo(0x00020804);
13: SortedList<string,string> MyList = new SortedList<string,string>();
14: MyList.Add("一(yi)", "data1");
15: MyList.Add("二(er)", "data2");
16: MyList.Add("三(san)", "data3");
17:
18: foreach(KeyValuePair<string, string> kvp in MyList )
19: {
20: Console.WriteLine("{0} is {1}", kvp.Key, kvp.Value);
21: }
22:
23: Console.ReadLine();
24: }
25: }
26:
结果:
可以用name为zh-CN_Stroke代替0x00020804:
1: Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN_Stroke");
字符串排序
Array 类提供了一个重载的Array.Sort方法,通过它可以根据 Thread.CurrentThread.CurrentCulture 属性来排序数据。
1: using System;
2: using System.Globalization;
3: using System.Threading;
4: using System.Collections;
5:
6: class Program
7: {
8: static void Main(string[] args)
9: {
10: string str1 = "三";
11: string str2 = "二";
12: string str3 = "一";
13:
14: Array stringArray = Array.CreateInstance(typeof(String), 3);
15: stringArray.SetValue(str1, 0);
16: stringArray.SetValue(str2, 1);
17: stringArray.SetValue(str3, 2);
18:
19: Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
20: Console.WriteLine("Default zh-CN:");
21: Array.Sort(stringArray);
22: PrintIndexAndValues(stringArray);
23:
24: Console.ReadLine();
25: }
26:
27: public static void PrintIndexAndValues(Array myArray)
28: {
29: for (int i = myArray.GetLowerBound(0);
30: i <= myArray.GetUpperBound(0); i++)
31: Console.WriteLine("\t[{0}]:\t{1}", i, myArray.GetValue(i));
32: }
33: }
默认中文拼音排序:
1: using System;
2: using System.Globalization;
3: using System.Threading;
4: using System.Collections;
5: using System.Collections.Generic;
6:
7: class Program
8: {
9: static void Main(string[] args)
10: {
11: string str1 = "三";
12: string str2 = "二";
13: string str3 = "一";
14:
15: Array stringArray = Array.CreateInstance(typeof(String), 3);
16: stringArray.SetValue(str1, 0);
17: stringArray.SetValue(str2, 1);
18: stringArray.SetValue(str3, 2);
19:
20: Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN_Stroke");
21: Console.WriteLine("zh-CN Stroke:");
22: Array.Sort(stringArray);
23: PrintIndexAndValues(stringArray);
24:
25: Console.ReadLine();
26: }
27:
28: public static void PrintIndexAndValues(Array myArray)
29: {
30: for (int i = myArray.GetLowerBound(0);
31: i <= myArray.GetUpperBound(0); i++)
32: Console.WriteLine("\t[{0}]:\t{1}", i, myArray.GetValue(i));
33: }
34: }
35:
中文笔画排序:
使用排序关键字
根据排序关键字方法,字符串中的每个字符都被赋予了多个类别的排序权重,包括字母、大小写和音调符号权重等。对于特定字符串,排序关键字可作为这些权重的存储库。例如,某个排序关键字可能依次包含一串字母权重、一串大小写权重等等。在.NET Framework 中,SortKey类将字符串映射到其排序关键字,反之亦然。您可以使用CompareInfo.GetSortKey方法为指定的字符串创建排序关键字。针对指定字符串生成的排序关键字是一个字节序列,它会根据您指定的 CurrentCulture 和 CompareOptions 的不同而变化。例如,如果在创建排序关键字时指定了 IgnoreCase,则使用此排序关键字进行字符串比较时将忽略大小写。为字符串创建了排序关键字之后,可以将其作为参数传递给 SortKey 类所提供的方法。SortKey.Compare方法允许您对排序关键字进行比较。由于 SortKey.Compare 执行的是简单的逐字节比较,因此它比使用String.Compare 要快很多。在用于排序的应用程序中,通过生成应用程序使用的所有字符串的排序关键字并将其存储下来,可以改进应用程序的性能。当需要进行排序或比较操作时,可以使用排序关键字而不是字符串。
1: using System;
2: using System.Globalization;
3: using System.Threading;
4:
5: class Program
6: {
7: static void Main(string[] args)
8: {
9: string str1 = "Apple";
10: string str2 = "Æble";
11:
12: CultureInfo dk = new CultureInfo("da-DK");
13: Thread.CurrentThread.CurrentCulture = dk;
14:
15: SortKey sc1 = dk.CompareInfo.GetSortKey(str1);
16: SortKey sc2 = dk.CompareInfo.GetSortKey(str2);
17:
18: Console.WriteLine(SortKey.Compare(sc1, sc2));
19:
20: CultureInfo enus = new CultureInfo("en-US");
21: Thread.CurrentThread.CurrentCulture = enus;
22:
23: SortKey sc3 = enus.CompareInfo.GetSortKey(str1);
24: SortKey sc4 = enus.CompareInfo.GetSortKey(str2);
25:
26: Console.WriteLine(SortKey.Compare(sc3, sc4));
27:
28: Console.ReadLine();
29: }
30: }
31:
结果: