针对特定区域性对数据进行比较和排序
用于对项排序的字母顺序和约定随区域性的不同而不同。 例如,排序顺序可以是区分大小写的,也可以是不区分大小写的。 它可以是基于发音的,也可以是基于字符外观的。 在东亚语言中,按文字的笔画和部首进行排序。 排序也可能随语言和区域性使用的字母表基本顺序的不同而不同。 例如,瑞典语中有“Æ”字符,它在字母表中排在“Z”之后。 德语中也有该字符,但它在字母表中同“ae”一样排在“A”之后。 全球通用的应用程序必须能够针对每个区域性对数据进行比较和排序,以支持区域性特定和语言特定的排序约定。
注意 有些时候不需要区分区域性的行为。 有关何时以及如何执行不区分区域性的操作的更多信息,请参见“不区分区域性的字符串操作”。
比较字符串
CompareInfo 类提供了一组方法,可用于执行区分区域性的字符串比较。 CultureInfo 类具有 CompareInfo 属性,该属性是此类的一个实例。 该属性定义如何针对特定区域性对字符串进行比较和排序。 String.Compare 方法使用 CompareInfo 属性中的信息来比较字符串。 如果 string1 小于 string2,则 String.Compare 方法返回一个负整数;如果 string1 和 string2 相等,则返回零;如果 string1 大于 string2,则返回一个正整数。
下面的代码示例演示如何根据用于执行比较的区域性,通过 String.Compare 方法以不同的方式来计算两个字符串。 首先,将 CurrentCulture 设置为 da-DK 以表示丹麦语(丹麦)区域性,并比较字符串“Apple”和“Æble”。 丹麦语将字符“Æ”视为单个字母,并在字母表中将其排在“Z”之后。 因此,对于丹麦语区域性,字符串“Æble”比“Apple”大。 接下来,将 CurrentCulture 设置为 en-US 以表示英语(美国)区域性,并再次比较字符串“Apple”和“Æble”。 这次,字符串“Æble”被确定为小于“Apple”。 英语语言将字符“Æ”视为一个特殊符号,并在字母表中将其排在字母“A”之前。
Imports System.Globalization
Imports System.Threading
Public Class TestClass
Public Shared Sub Main()
Dim str1 As String = "Apple"
Dim str2 As String = "Æble"
' Set the current culture to Danish in Denmark.
Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
Dim result1 As Integer = [String].Compare(str1, str2)
Console.WriteLine("When the CurrentCulture is ""da-DK"",")
Console.WriteLine("the result of comparing_{0} with {1} is: {2}",
str1, str2, result1)
' Set the current culture to English in the U.S.
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
Dim result2 As Integer = [String].Compare(str1, str2)
Console.WriteLine("When the CurrentCulture is""en-US"",")
Console.WriteLine("the result of comparing {0} with {1} is: {2}",
str1, str2,result2)
End Sub
End Class
' The example displays the following output:
' When the CurrentCulture is "da-DK",
' the result of comparing Apple with Æble is: -1
'
' When the CurrentCulture is "en-US",
' the result of comparing Apple with Æble is: 1
using System;
using System.Globalization;
using System.Threading;
public class CompareStringSample
{
public static void Main()
{
string str1 = "Apple";
string str2 = "Æble";
// Sets the CurrentCulture to Danish in Denmark.
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
// Compares the two strings.
int result1 = String.Compare(str1, str2);
Console.WriteLine("\nWhen the CurrentCulture is \"da-DK\",\nthe " +
"result of comparing {0} with {1} is: {2}", str1, str2,
result1);
// Sets the CurrentCulture to English in the U.S.
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
// Compares the two strings.
int result2 = String.Compare(str1, str2);
Console.WriteLine("\nWhen the CurrentCulture is \"en-US\",\nthe " +
"result of comparing {0} with {1} is: {2}", str1, str2,
result2);
}
}
// The example displays the following output:
// When the CurrentCulture is "da-DK",
// the result of comparing Apple with Æble is: -1
//
// When the CurrentCulture is "en-US",
// the result of comparing Apple with Æble is: 1
有关比较字符串的更多信息,请参见比较字符串。
使用替换排序顺序
某些区域性支持多种排序顺序。 例如,名称为 zh-CN 的区域性中文 (PRC) 支持按发音排序(默认)和按笔画数排序。 当应用程序使用区域性名称(如 zh-CN)创建 CultureInfo 对象时,使用的是默认排序顺序。 若要指定替换排序顺序,应用程序应使用替换排序顺序的标识符来创建 CultureInfo 对象。 然后,应用程序应从 CompareInfo 获取 CompareInfo 对象,以便在字符串比较中使用。 或者,应用程序可以使用 CompareInfo.GetCompareInfo 方法直接创建一个 CompareInfo 对象,指定替换排序顺序的标识符。
下表列出了支持替换排序顺序的区域性以及默认和替换排序顺序的标识符。
区域性名称 |
区域性 |
默认排序名称和标识符 |
替换排序名称和标识符 |
---|---|---|---|
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 |
搜索字符串
应用程序可以使用重载的 CompareInfo.IndexOf 方法在指定字符串中检索某个字符或子字符串的从零开始的索引。 如果在指定字符串中未找到该字符或子字符串,此方法将检索到一个负整数。 在使用 CompareInfo.IndexOf 搜索指定字符时,应用程序应考虑到,在执行比较的方式上,接受 CompareOptions 参数的方法重载与不接受此参数的方法重载是不同的。 不接受 CompareOptions 参数的方法重载在搜索字符类型时,执行的是区分区域性的搜索。 这就是说,如果一个 Unicode 值表示预先撰写的字符,如连字“Æ”(\u00C6),则根据区域性的不同,它可能被视为等效于它各部分以正确顺序排列的任何形式,如“AE”(\u0041\u0045)。 若要执行顺序(不区分区域性)搜索(即,仅当 Unicode 值相同时,两个字符类型才视为相等),应用程序应使用接受 CompareOptions 参数的 CompareInfo.IndexOf 重载之一,并将该参数设置为 Ordinal 值。
应用程序也可以使用搜索字符的 String.IndexOf 方法重载来执行序号(不区分区域性)搜索。 请注意,搜索字符串的此方法重载执行的是区分区域性的搜索。
下面的代码示例演示在不同区域性下,IndexOf 方法的检索结果的差异。 针对 da-DK 创建 CultureInfo 对象,表示区域性丹麦语(丹麦)。 接下来,使用 CompareInfo.IndexOf 方法的重载在字符串“Æble”和“aeble”中搜索字符“Æ”。请注意,对于 da-DK,接受设置为 Ordinal 的 CompareOptions 参数的 CompareInfo.IndexOf 方法与不接受此参数的同一方法检索到的内容是一样的。 字符“Æ”仅被视为等效于 Unicode 代码值 \u00E6。
Imports System.Globalization
Imports System.Threading
Public Class CompareClass
Public Shared Sub Main()
Dim str1 As String = "Æble"
Dim str2 As String = "aeble"
Dim find As Char = "Æ"
' Creates a CultureInfo for Danish in Denmark.
Dim ci As New CultureInfo("da-DK")
Dim result1 As Integer = ci.CompareInfo.IndexOf(str1, find)
Dim result2 As Integer = ci.CompareInfo.IndexOf(str2, find)
Dim result3 As Integer = ci.CompareInfo.IndexOf(str1, find, _
CompareOptions.Ordinal)
Dim result4 As Integer = ci.CompareInfo.IndexOf(str2, find, _
CompareOptions.Ordinal)
Console.WriteLine("CultureInfo is set to {0}",
ci.DisplayName)
Console.WriteLine()
Console.WriteLine("Using CompareInfo.IndexOf(string, char) method")
Console.WriteLine("the result of searching for {0} in the string {1} is: {2}",
find, str1, result1)
Console.WriteLine()
Console.WriteLine("Using CompareInfo.IndexOf(string, char) method")
Console.WriteLine("the result of searching for {0} in the string {1} is: {2}",
find, str2, result2)
Console.WriteLine()
Console.WriteLine("Using CompareInfo.IndexOf(string, char, CompareOptions) method")
Console.WriteLine("the result of searching for {0} in the string {1} is: {2}",
find, str1, result3)
Console.WriteLine()
Console.WriteLine("Using CompareInfo.IndexOf(string, char, CompareOptions) method")
Console.WriteLine("the result of searching for {0} in the string {1} is: {2}",
find, str2, result4)
End Sub
End Class
' The example displays the following output:
' CultureInfo is set to Danish (Denmark)
'
' Using CompareInfo.IndexOf(string, char) method
' the result of searching for Æ in the string Æble is: 0
'
' Using CompareInfo.IndexOf(string, char) method
' the result of searching for Æ in the string aeble is: -1
'
' Using CompareInfo.IndexOf(string, char, CompareOptions) method
' the result of searching for Æ in the string Æble is: 0
'
' Using CompareInfo.IndexOf(string, char, CompareOptions) method
' the result of searching for Æ in the string aeble is: -1
using System;
using System.Globalization;
using System.Threading;
public class CompareClass
{
public static void Main()
{
string str1 = "Æble";
string str2 = "aeble";
char find = 'Æ';
// Creates a CultureInfo for Danish in Denmark.
CultureInfo ci= new CultureInfo("da-DK");
int result1 = ci.CompareInfo.IndexOf(str1, find);
int result2 = ci.CompareInfo.IndexOf(str2, find);
int result3 = ci.CompareInfo.IndexOf(str1, find,
CompareOptions.Ordinal);
int result4 = ci.CompareInfo.IndexOf(str2, find,
CompareOptions.Ordinal);
Console.WriteLine("\nCultureInfo is set to {0} ", ci.DisplayName);
Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) " +
"method\nthe result of searching for {0} in the string {1} is: {2}",
find, str1, result1);
Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char) " +
"method\nthe result of searching for {0} in the string {1} is: {2}",
find, str2, result2);
Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, " +
"CompareOptions) method\nthe result of searching for {0} in the " +
"string {1} is: {2}", find, str1, result3);
Console.WriteLine("\nUsing CompareInfo.IndexOf(string, char, " +
"CompareOptions) method\nthe result of searching for {0} in the " +
"string {1} is: {2}", find, str2, result4);
}
}
// The example displays the following output:
// CultureInfo is set to Danish (Denmark)
//
// Using CompareInfo.IndexOf(string, char) method
// the result of searching for Æ in the string Æble is: 0
//
// Using CompareInfo.IndexOf(string, char) method
// the result of searching for Æ in the string aeble is: -1
//
// Using CompareInfo.IndexOf(string, char, CompareOptions) method
// the result of searching for Æ in the string Æble is: 0
//
// Using CompareInfo.IndexOf(string, char, CompareOptions) method
// the result of searching for Æ in the string aeble is: -1
如果应用程序用 CultureInfo ci = new CultureInfo ("en-US") 替换 CultureInfo ci = new CultureInfo ("da-DK"),则带有设置为 Ordinal 的 CompareOptions 参数的 CompareInfo.IndexOf 方法与不带有此参数的同一方法将检索到不同结果。 CompareInfo.IndexOf 方法执行的区分区域性的比较认为字符“Æ”与其组成部分“ae”等效。 CompareInfo.IndexOf 方法执行的序号(不区分区域性)比较则不检索与“ae”等效的字符“Æ”,这是因为它们的 Unicode 代码值不匹配。
针对 en-US(表示英语(美国))重新编译并执行这些代码时,将产生以下输出:
The CurrentCulture property is set to English (United States)
Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string Æble is: 0
Using CompareInfo.IndexOf(string, char) method
the result of searching for Æ in the string aeble is: 0
Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string Æble is: 0
Using CompareInfo.IndexOf(string, char, CompareOptions) method
the result of searching for Æ in the string aeble is: -1
对字符串进行排序
Array 类提供了重载的 Array.Sort 方法,应用程序可根据 CurrentCulture 属性使用该方法对数组进行排序。 在下面的示例中,将创建一个由三个字符串组成的数组。 首先,将 Thread.CurrentThread.CurrentCulture 属性设置为 en-US,并调用 Array.Sort 方法。 结果排序顺序基于英语(美国)区域性的排序约定。 接下来,将 Thread.CurrentThread.CurrentCulture 属性设置为 da-DK,并再次调用 Array.Sort 方法。 请注意,结果排序顺序与使用 en-US 时的结果是不一样的,因为使用的是 da-DK 的排序约定。
Imports System.Globalization
Imports System.IO
Imports System.Threading
Public Class TextToFile
Public Shared Sub Main()
' Creates and initializes a new array to store
' these date/time objects.
Dim stringArray() As String = { "Apple", "Æble", "Zebra"}
' Displays the values of the array.
Console.WriteLine("The original string array:")
PrintIndexAndValues(stringArray)
' Set the CurrentCulture to "en-US".
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
' Sort the values of the Array.
Array.Sort(stringArray)
' Display the values of the array.
Console.WriteLine("After sorting for the ""en-US"" culture:")
PrintIndexAndValues(stringArray)
' Set the CurrentCulture to "da-DK".
Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
' Sort the values of the Array.
Array.Sort(stringArray)
' Displays the values of the Array.
Console.WriteLine("After sorting for the culture ""da-DK"":")
PrintIndexAndValues(stringArray)
End Sub
Public Shared Sub PrintIndexAndValues(myArray() As String)
For i As Integer = myArray.GetLowerBound(0) To myArray.GetUpperBound(0)
Console.WriteLine("[{0}]: {1}", i, myArray(i))
Next
Console.WriteLine()
End Sub
End Class
' The example displays the following output:
' The original string array:
' [0]: Apple
' [1]: Æble
' [2]: Zebra
'
' After sorting for the "en-US" culture:
' [0]: Æble
' [1]: Apple
' [2]: Zebra
'
' After sorting for the culture "da-DK":
' [0]: Apple
' [1]: Zebra
' [2]: Æble
using System;
using System.Globalization;
using System.Threading;
public class ArraySort
{
public static void Main(String[] args)
{
// Create and initialize a new array to store the strings.
string[] stringArray = { "Apple", "Æble", "Zebra"};
// Display the values of the array.
Console.WriteLine( "The original string array:");
PrintIndexAndValues(stringArray);
// Set the CurrentCulture to "en-US".
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
// Sort the values of the array.
Array.Sort(stringArray);
// Display the values of the array.
Console.WriteLine("After sorting for the culture \"en-US\":");
PrintIndexAndValues(stringArray);
// Set the CurrentCulture to "da-DK".
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
// Sort the values of the Array.
Array.Sort(stringArray);
// Display the values of the array.
Console.WriteLine("After sorting for the culture \"da-DK\":");
PrintIndexAndValues(stringArray);
}
public static void PrintIndexAndValues(string[] myArray)
{
for (int i = myArray.GetLowerBound(0); i <=
myArray.GetUpperBound(0); i++ )
Console.WriteLine("[{0}]: {1}", i, myArray[i]);
Console.WriteLine();
}
}
// The example displays the following output:
// The original string array:
// [0]: Apple
// [1]: Æble
// [2]: Zebra
//
// After sorting for the "en-US" culture:
// [0]: Æble
// [1]: Apple
// [2]: Zebra
//
// After sorting for the culture "da-DK":
// [0]: Apple
// [1]: Zebra
// [2]: Æble
使用排序关键字
排序关键字用于支持区分区域性的排序。 根据“Unicode 标准”,字符串中的每个字符都有若干类别给定的排序权重,包括字母、大小写和音调权重。 排序关键字充当特定字符串的这些权重的储存库。 例如,排序关键字可以包含字母权重字符串,后跟大小写权重字符串等。 有关排序关键字概念的其他信息,请参见位于 Unicode home page(Unicode 主页)上的“The Unicode Standard”(Unicode 标准)。
在 .NET Framework 中,SortKey 类将字符串映射到它们的排序关键字,反之亦然。 应用程序可以使用 CompareInfo.GetSortKey 方法为指定的字符串创建排序关键字。 指定字符串的结果排序关键字是一个字节序列,它可能会因指定的 CurrentCulture 和 CompareOptions 值的不同而不同。 例如,如果在创建排序关键字时,应用程序指定值 IgnoreCase,则使用该排序关键字进行的字符串比较操作将忽略大小写。
为字符串创建排序关键字后,应用程序可以将该关键字作为参数传递给 SortKey 类提供的方法。 SortKey.Compare 方法可以对排序关键字进行比较。 此方法执行简单的逐字节比较,因此,使用起来比 String.Compare 快很多。 在进行大量排序的应用程序中,通过为所用的所有字符串生成并存储排序关键字,可以提高性能。 需要执行排序或比较操作时,应用程序可以使用这些排序关键字,而不必使用字符串。
下面的代码示例在 CurrentCulture 设置为 da-DK 时,为两个字符串创建排序关键字。 它使用 SortKey.Compare 方法比较这两个字符串,并显示结果。 如果 string1 小于 string2,该方法返回一个负整数;如果 string1 和 string2 相等,则返回零 (0);如果 string1 大于 string2,则返回一个正整数。 接下来,将 Thread.CurrentThread.CurrentCulture 属性设置为 en-US,并为这些字符串创建排序关键字。 然后对字符串的排序关键字进行比较并显示结果。 请注意,排序结果因 CurrentCulture 的设置的不同而不同。 尽管下面代码示例的结果与本主题前面比较字符串示例中这些字符串的比较结果相同,但使用 SortKey.Compare 方法比使用 String.Compare 方法更快。
Imports System.Globalization
Imports System.Threading
Public Class SortKeySample
Public Shared Sub Main()
Dim str1 As [String] = "Apple"
Dim str2 As [String] = "Æble"
' Set the CurrentCulture to "da-DK".
Dim dk As New CultureInfo("da-DK")
Thread.CurrentThread.CurrentCulture = dk
' Create a culturally sensitive sort key for str1.
Dim sc1 As SortKey = dk.CompareInfo.GetSortKey(str1)
' Create a culturally sensitive sort key for str2.
Dim sc2 As SortKey = dk.CompareInfo.GetSortKey(str2)
' Compare the two sort keys and display the results.
Dim result1 As Integer = SortKey.Compare(sc1, sc2)
Console.WriteLine("When the current culture is ""da-DK"",")
Console.WriteLine("the result of comparing {0} with {1} is: {2}",
str1, str2, result1)
Console.WriteLine()
' Set the CurrentCulture to "en-US".
Dim enus As New CultureInfo("en-US")
Thread.CurrentThread.CurrentCulture = enus
' Create a culturally sensitive sort key for str1.
Dim sc3 As SortKey = enus.CompareInfo.GetSortKey(str1)
' Create a culturally sensitive sort key for str1.
Dim sc4 As SortKey = enus.CompareInfo.GetSortKey(str2)
' Compare the two sort keys and display the results.
Dim result2 As Integer = SortKey.Compare(sc3, sc4)
Console.WriteLine("When the CurrentCulture is ""en-US"",")
Console.WriteLine("the result of comparing {0} with {1} is: {2}",
str1, str2, result2)
End Sub
End Class
' The example displays the following output:
' When the current culture is "da-DK",
' the result of comparing Apple with Æble is: -1
'
' When the CurrentCulture is "en-US",
' the result of comparing Apple with Æble is: 1
using System;
using System.Threading;
using System.Globalization;
public class SortKeySample
{
public static void Main(String[] args)
{
String str1 = "Apple";
String str2 = "Æble";
// Set the CurrentCulture to "da-DK".
CultureInfo dk = new CultureInfo("da-DK");
Thread.CurrentThread.CurrentCulture = dk;
// Create a culturally sensitive sort key for str1.
SortKey sc1 = dk.CompareInfo.GetSortKey(str1);
// Create a culturally sensitive sort key for str2.
SortKey sc2 = dk.CompareInfo.GetSortKey(str2);
// Compare the two sort keys and display the results.
int result1 = SortKey.Compare(sc1, sc2);
Console.WriteLine("When the CurrentCulture is \"da-DK\",");
Console.WriteLine("the result of comparing {0} with {1} is: {2}\n",
str1, str2, result1);
// Set the CurrentCulture to "en-US".
CultureInfo enus = new CultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = enus ;
// Create a culturally sensitive sort key for str1.
SortKey sc3 = enus.CompareInfo.GetSortKey(str1);
// Create a culturally sensitive sort key for str1.
SortKey sc4 = enus.CompareInfo.GetSortKey(str2);
// Compare the two sort keys and display the results.
int result2 = SortKey.Compare(sc3, sc4);
Console.WriteLine("When the CurrentCulture is \"en-US\",");
Console.WriteLine("the result of comparing {0} with {1} is: {2}",
str1, str2, result2);
}
}
// The example displays the following output:
// When the CurrentCulture is "da-DK",
// the result of comparing Apple with Æble is: -1
//
// When the CurrentCulture is "en-US",
// the result of comparing Apple with Æble is: 1
正常化
在排序之前,应用程序可以将字符串正常化为大写或小写。 字符串排序和大小写转换规则是语言特定的。 例如,即使在拉丁语系中,也存在不同的撰写和排序规则。 只有在少数几种语言(包括英语)中,排序顺序和码位顺序是匹配的,例如 A [65] 位于 B [66] 之前。
应用程序不应依赖码位来执行精确的排序和字符串比较。 此外,.NET Framework 并不强制或保证执行特定形式的正常化。 您负责在所开发的应用程序中执行适当的正常化。
有关字符串正常化的更多信息,请参见正常化和排序。