J'ai besoin de comparer 2 chaînes en C # et de traiter les lettres accentuées de la même manière que les lettres non accentuées. Par exemple:
string s1 = "hello";
string s2 = "héllo";
s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase);
s1.Equals(s2, StringComparison.OrdinalIgnoreCase);
Ces 2 chaînes doivent être identiques (en ce qui concerne ma demande), mais ces deux déclarations sont fausses. Existe-t-il un moyen en C # de le faire?
EDIT 2012-01-20: Oh boy! La solution était tellement plus simple et a été dans le cadre presque pour toujours. Comme l'a souligné knightpfhor :
string.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace);
Voici une fonction qui supprime les signes diacritiques d'une chaîne:
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);
}
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 "he <acute> llo", qui à son tour devient "bonjour".
Debug.Assert("hello"==RemoveDiacritics("héllo"));
Remarque: Voici une version plus compacte .NET4 + conviviale de la même fonction:
static string RemoveDiacritics(string text)
{
return string.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
string s1 = "hello";
string s2 = "héllo";
if (String.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace) == 0)
{
// both strings are equal
}
ou si vous voulez que la comparaison soit aussi insensible à la casse
string s1 = "HEllO";
string s2 = "héLLo";
if (String.Compare(s1, s2, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase) == 0)
{
// both strings are equal
}
La méthode suivante CompareIgnoreAccents(...)
fonctionne sur vos données d'exemple. Voici l'article où j'ai obtenu mes informations générales: 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)));
}
Je pense qu'une méthode d'extension serait mieux:
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)));
}
Ensuite, l'utilisation serait la suivante:
if(string.Compare(s1.RemoveAccents(), s2.RemoveAccents(), true) == 0) {
...
J'ai dû 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 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;
}
Et pour un paquebot freaks;)
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;
}
Accents incensifs et non sensibles à la casse
value.ToString().StartsWith(str, CultureInfo.InvariantCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase)
Un moyen plus simple de supprimer les accents:
Dim source As String = "áéíóúç"
Dim result As String
Dim bytes As Byte() = Encoding.GetEncoding("Cyrillic").GetBytes(source)
result = Encoding.ASCII.GetString(bytes)