2008-12-11 43 views
112

我需要比较C#中的2个字符串,并将重音字母与非重音字母相同。例如:忽略字符串比较中的重音字母

string s1 = "hello"; 
string s2 = "héllo"; 

s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase); 
s1.Equals(s2, StringComparison.OrdinalIgnoreCase); 

这两个字符串必须是相同的(至于我的应用程序而言),但是这两个语句的计算结果为假。 C#中有没有办法做到这一点?

回答

211

编辑2012-01-20:哦,小子!解决方案非常简单,几乎永远在框架中。 As pointed out by 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); 
} 

更多细节on MichKap's blogRIP...)。

原理是,它将'é'变成2个连续字符'e',急剧。 然后它遍历字符并跳过变音符号。

“héllo”变成“他<锐利> llo”,其反过来变成“你好”。

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); 
} 
-3

在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 
*/ 

为此重音符号的语言

例如,你将需要获得文化测试,然后根据该字符串。

http://msdn.microsoft.com/en-us/library/hyxc48dt.aspx

+0

这是比直接比较字符串更好的方法,但它仍然考虑基本字母及其重音版本*不同*。因此,它不回答原来的问题,它希望忽略重音。 – 2013-05-15 14:43:49

6

下面的方法对你的榜样的数据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) { 
    ... 
+1

这使重音字母'?' – onmyway133 2012-11-07 04:51:20

+3

这是一个破坏性的比较,例如,ā和ē将被视为平等。你丢失了0xFF以上的任何字符,并且不能保证这些字符串是相同的 - 忽略 - 重音。 – Abel 2013-05-07 15:18:02

+0

你也会失去像ñ一样的东西。如果你问我,不是一个解决方案。 – 2016-02-02 08:45:36

106

如果您不需要字符串转换,你只是想检查平等,你可以使用

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 
} 
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; 
    } 

口音incensitive和壳体incensitive startsWith可以称为像这样

value.ToString().StartsWith(str, CultureInfo.InvariantCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) 
0

甲更简单的删除口音的方法:

Dim source As String = "áéíóúç" 
    Dim result As String 

    Dim bytes As Byte() = Encoding.GetEncoding("Cyrillic").GetBytes(source) 
    result = Encoding.ASCII.GetString(bytes) 
相关问题