Ignorer les lettres accentuées dans la comparaison de chaînes

J’ai besoin de comparer 2 chaînes en C # et de traiter les lettres accentuées comme des lettres non accentuées. Par exemple:

ssortingng s1 = "hello"; ssortingng s2 = "héllo"; s1.Equals(s2, SsortingngComparison.InvariantCultureIgnoreCase); s1.Equals(s2, SsortingngComparison.OrdinalIgnoreCase); 

Ces deux chaînes doivent être identiques (en ce qui concerne mon application), mais ces deux déclarations sont considérées comme fausses. Y at-il un moyen en C # pour faire cela?

EDIT 2012-01-20: Oh mon garçon! La solution était tellement plus simple et a été dans le cadre presque pour toujours. Comme le souligne Knightpfhor :

 ssortingng.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace); 

Voici une fonction qui supprime les signes diacritiques d’une chaîne:

 static ssortingng RemoveDiacritics(ssortingng text) { ssortingng formD = text.Normalize(NormalizationForm.FormD); SsortingngBuilder sb = new SsortingngBuilder(); foreach (char ch in formD) { UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch); if (uc != UnicodeCategory.NonSpacingMark) { sb.Append(ch); } } return sb.ToSsortingng().Normalize(NormalizationForm.FormC); } 

Plus de détails sur le blog de MichKap ( RIP … ).

Le principe est qu’il transforme «é» en 2 caractères successifs «e», aigus. Il parcourt ensuite les caractères et ignore les signes diacritiques.

“héllo” devient “il llo”, qui devient à son tour “bonjour”.

 Debug.Assert("hello"==RemoveDiacritics("héllo")); 

Note: Voici une version plus compacte .NET4 + conviviale de la même fonction:

 static ssortingng RemoveDiacritics(ssortingng text) { return ssortingng.Concat( text.Normalize(NormalizationForm.FormD) .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch)!= UnicodeCategory.NonSpacingMark) ).Normalize(NormalizationForm.FormC); } 

Si vous n’avez pas besoin de convertir la chaîne et que vous souhaitez simplement vérifier l’égalité, vous pouvez utiliser

 ssortingng s1 = "hello"; ssortingng s2 = "héllo"; if (Ssortingng.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace) == 0) { // both ssortingngs are equal } 

ou si vous voulez que la comparaison soit aussi insensible à la casse

 ssortingng s1 = "HEllO"; ssortingng s2 = "héLLo"; if (Ssortingng.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) == 0) { // both ssortingngs are equal } 

La méthode suivante CompareIgnoreAccents(...) fonctionne sur vos exemples de données. Voici l’article sur lequel j’ai trouvé mes informations de base: http://www.codeproject.com/KB/cs/EncodingAccents.aspx

 private static bool CompareIgnoreAccents(ssortingng s1, ssortingng s2) { return ssortingng.Compare( RemoveAccents(s1), RemoveAccents(s2), SsortingngComparison.InvariantCultureIgnoreCase) == 0; } private static ssortingng RemoveAccents(ssortingng s) { Encoding destEncoding = Encoding.GetEncoding("iso-8859-8"); return destEncoding.GetSsortingng( Encoding.Convert(Encoding.UTF8, destEncoding, Encoding.UTF8.GetBytes(s))); } 

Je pense qu’une méthode d’extension serait préférable:

 public static ssortingng RemoveAccents(this ssortingng s) { Encoding destEncoding = Encoding.GetEncoding("iso-8859-8"); return destEncoding.GetSsortingng( Encoding.Convert(Encoding.UTF8, destEncoding, Encoding.UTF8.GetBytes(s))); } 

Alors l’utilisation serait la suivante:

 if(ssortingng.Compare(s1.RemoveAccents(), s2.RemoveAccents(), true) == 0) { ... 

Je devais faire quelque chose de similaire mais avec une méthode StartsWith. Voici une solution simple dérivée de @Serge – appTranslator.

Voici une méthode d’extension:

  public static bool StartsWith(this ssortingng str, ssortingng value, CultureInfo culture, CompareOptions options) { if (str.Length >= value.Length) return ssortingng.Compare(str.Subssortingng(0, value.Length), value, culture, options) == 0; else return false; } 

Et pour les monstres les monstres;)

  public static bool StartsWith(this ssortingng str, ssortingng value, CultureInfo culture, CompareOptions options) { return str.Length >= value.Length && ssortingng.Compare(str.Subssortingng(0, value.Length), value, culture, options) == 0; } 

Accent incensif et démarches incensibles qui peuvent être appelées comme ceci

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

Un moyen plus simple de supprimer les accents:

  Dim source As Ssortingng = "áéíóúç" Dim result As Ssortingng Dim bytes As Byte() = Encoding.GetEncoding("Cyrillic").GetBytes(source) result = Encoding.ASCII.GetSsortingng(bytes) 

essayez cette surcharge sur la méthode Ssortingng.Compare.

Ssortingng.Compare, méthode (Ssortingng, Ssortingng, Boolean, CultureInfo)

Il produit une valeur int basée sur les opérations de comparaison, y compris cultureinfo. L’exemple de la page compare “Change” en-US et en-CZ. CH en en CZ est une simple “lettre”.

exemple du lien

 using System; using System.Globalization; class Sample { public static void Main() { Ssortingng str1 = "change"; Ssortingng str2 = "dollar"; Ssortingng relation = null; relation = symbol( Ssortingng.Compare(str1, str2, false, new CultureInfo("en-US")) ); Console.WriteLine("For en-US: {0} {1} {2}", str1, relation, str2); relation = symbol( Ssortingng.Compare(str1, str2, false, new CultureInfo("cs-CZ")) ); Console.WriteLine("For cs-CZ: {0} {1} {2}", str1, relation, str2); } private static Ssortingng symbol(int r) { Ssortingng 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 */ 

pour les langues accentuées, vous devrez donc obtenir la culture, puis tester les chaînes en fonction de cela.

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