我需要在C#中比较2个字符串,并将重音字母与非重音字母相同。例如:
string s1 = "hello";
string s2 = "héllo";
s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase);
s1.Equals(s2, StringComparison.OrdinalIgnoreCase);
这两个字符串必须相同(就我的应用程序而言),但是这两个语句的评估结果均为false。C#中有办法做到这一点吗?
我需要在C#中比较2个字符串,并将重音字母与非重音字母相同。例如:
string s1 = "hello";
string s2 = "héllo";
s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase);
s1.Equals(s2, StringComparison.OrdinalIgnoreCase);
这两个字符串必须相同(就我的应用程序而言),但是这两个语句的评估结果均为false。C#中有办法做到这一点吗?
Answers:
编辑2012-01-20:天哪!该解决方案非常简单,并且几乎永远存在于框架中。正如knightpfhor所指出的:
string.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace);
这是一个从字符串中去除变音符号的函数:
static string RemoveDiacritics(string text)
{
string formD = text.Normalize(NormalizationForm.FormD);
StringBuilder sb = new StringBuilder();
foreach (char ch in formD)
{
UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch);
if (uc != UnicodeCategory.NonSpacingMark)
{
sb.Append(ch);
}
}
return sb.ToString().Normalize(NormalizationForm.FormC);
}
原理是将'é'转换为2个连续的字符'e',即尖峰。然后,它遍历字符并跳过变音符号。
“héllo”变成“ he <acute> llo”,后者又变成“ hello”。
Debug.Assert("hello"==RemoveDiacritics("héllo"));
注意:这是同一功能的更紧凑的.NET4 +友好版本:
static string RemoveDiacritics(string text)
{
return string.Concat(
text.Normalize(NormalizationForm.FormD)
.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch)!=
UnicodeCategory.NonSpacingMark)
).Normalize(NormalizationForm.FormC);
}
如果您不需要转换字符串,而只想检查是否相等,则可以使用
string s1 = "hello";
string s2 = "héllo";
if (String.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace) == 0)
{
// both strings are equal
}
或者如果您也希望比较也不区分大小写
string s1 = "HEllO";
string s2 = "héLLo";
if (String.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) == 0)
{
// both strings are equal
}
以下方法CompareIgnoreAccents(...)
适用于您的示例数据。这是我获得背景信息的文章:http : //www.codeproject.com/KB/cs/EncodingAccents.aspx
private static bool CompareIgnoreAccents(string s1, string s2)
{
return string.Compare(
RemoveAccents(s1), RemoveAccents(s2), StringComparison.InvariantCultureIgnoreCase) == 0;
}
private static string RemoveAccents(string s)
{
Encoding destEncoding = Encoding.GetEncoding("iso-8859-8");
return destEncoding.GetString(
Encoding.Convert(Encoding.UTF8, destEncoding, Encoding.UTF8.GetBytes(s)));
}
我认为扩展方法会更好:
public static string RemoveAccents(this string s)
{
Encoding destEncoding = Encoding.GetEncoding("iso-8859-8");
return destEncoding.GetString(
Encoding.Convert(Encoding.UTF8, destEncoding, Encoding.UTF8.GetBytes(s)));
}
然后的用法是这样的:
if(string.Compare(s1.RemoveAccents(), s2.RemoveAccents(), true) == 0) {
...
我必须执行类似的操作,但要使用StartsWith方法。这是从@Serge-appTranslator派生的简单解决方案。
这是一个扩展方法:
public static bool StartsWith(this string str, string value, CultureInfo culture, CompareOptions options)
{
if (str.Length >= value.Length)
return string.Compare(str.Substring(0, value.Length), value, culture, options) == 0;
else
return false;
}
对于一个班轮怪胎;)
public static bool StartsWith(this string str, string value, CultureInfo culture, CompareOptions options)
{
return str.Length >= value.Length && string.Compare(str.Substring(0, value.Length), value, culture, options) == 0;
}
口音香气和案例香气startsWith可以这样称呼
value.ToString().StartsWith(str, CultureInfo.InvariantCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase)
在String.Compare方法上尝试此重载。
String.Compare方法(字符串,字符串,布尔值,CultureInfo)
它基于包括cultureinfo的比较操作产生一个int值。该页面中的示例比较了en-US和en-CZ中的“更改”。en-CZ中的CH是单个“字母”。
链接中的示例
using System;
using System.Globalization;
class Sample {
public static void Main() {
String str1 = "change";
String str2 = "dollar";
String relation = null;
relation = symbol( String.Compare(str1, str2, false, new CultureInfo("en-US")) );
Console.WriteLine("For en-US: {0} {1} {2}", str1, relation, str2);
relation = symbol( String.Compare(str1, str2, false, new CultureInfo("cs-CZ")) );
Console.WriteLine("For cs-CZ: {0} {1} {2}", str1, relation, str2);
}
private static String symbol(int r) {
String s = "=";
if (r < 0) s = "<";
else if (r > 0) s = ">";
return s;
}
}
/*
This example produces the following results.
For en-US: change < dollar
For cs-CZ: change > dollar
*/
因此,对于重读语言,您需要了解文化,然后根据该语言测试字符串。
string.Normalize
?