РЕДАКТИРОВАТЬ 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);
}
Подробнее в блоге MichKap ( RIP ... ).
Принцип состоит в том, что он превращает «é» в два последовательных символа «е» с ударением. Затем он перебирает символы и пропускает диакритические знаки.
«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.Normalize
?Если вам не нужно преобразовывать строку, и вы просто хотите проверить равенство, вы можете использовать
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.aspxprivate 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; }
Нечувствительный к акценту и нечувствительный к регистру startWith можно назвать так
value.ToString().StartsWith(str, CultureInfo.InvariantCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase)
источник
Более простой способ убрать акценты:
Dim source As String = "áéíóúç" Dim result As String Dim bytes As Byte() = Encoding.GetEncoding("Cyrillic").GetBytes(source) result = Encoding.ASCII.GetString(bytes)
источник
попробуйте эту перегрузку в методе String.Compare.
Метод String.Compare (String, String, Boolean, CultureInfo)
Он создает значение типа int на основе операций сравнения, включая культуру. пример на странице сравнивает "Изменить" в en-US и en-CZ. CH в en-CZ - это одна буква.
пример по ссылке
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
источник