2010-09-22 4 views
13

Possible en double:
How do I remove diacritics (accents) from a string in .NET?Comment puis-je supprimer des accents sur une chaîne?

je la chaîne suivante

áéíóú 

que je dois le convertir en

aeiou 

Comment puis-je y arriver? (Je ne ai pas besoin de comparer, j'ai besoin la nouvelle chaîne pour sauver)


pas un doublon de How do I remove diacritics (accents) from a string in .NET?. La réponse acceptée n'explique rien et c'est pourquoi je l'ai "rouverte".

+0

Merde, voulez annuler ma réouverture - c'est certainement un doublon. @BrunoLM si vous n'aimez pas la réponse, il est préférable de mettre une prime sur ce que demander à un dup –

Répondre

21

Cela dépend des besoins. Pour la plupart des utilisations, puis normaliser à NFD, puis filtrant tous les caractères de combinaison fera l'affaire. Dans certains cas, la normalisation vers NFKD est plus appropriée (si vous souhaitez également supprimer certaines distinctions entre les caractères).

D'autres distinctions ne seront pas prises en compte, notamment les caractères latins caressés. Il n'y a pas non plus de méthode spécifique non locale pour certains (devrait être considérée comme équivalente à l ou w?), Vous devrez donc peut-être personnaliser au-delà.

Il y a aussi des cas où NFD et NFKD ne fonctionnent pas comme prévu, pour permettre la cohérence entre les versions Unicode.

Par conséquent:

public static IEnumerable<char> RemoveDiacriticsEnum(string src, bool compatNorm, Func<char, char> customFolding) 
{ 
    foreach(char c in src.Normalize(compatNorm ? NormalizationForm.FormKD : NormalizationForm.FormD)) 
    switch(CharUnicodeInfo.GetUnicodeCategory(c)) 
    { 
     case UnicodeCategory.NonSpacingMark: 
     case UnicodeCategory.SpacingCombiningMark: 
     case UnicodeCategory.EnclosingMark: 
     //do nothing 
     break; 
     default: 
     yield return customFolding(c); 
     break; 
    } 
} 
public static IEnumerable<char> RemoveDiacriticsEnum(string src, bool compatNorm) 
{ 
    return RemoveDiacritics(src, compatNorm, c => c); 
} 
public static string RemoveDiacritics(string src, bool compatNorm, Func<char, char> customFolding) 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach(char c in RemoveDiacriticsEnum(src, compatNorm, customFolding)) 
    sb.Append(c); 
    return sb.ToString(); 
} 
public static string RemoveDiacritics(string src, bool compatNorm) 
{ 
    return RemoveDiacritics(src, compatNorm, c => c); 
} 

Ici, nous avons un défaut pour les cas de problèmes mentionnés ci-dessus, qui les ignore tout simplement. Nous avons également divisé une chaîne en générant l'énumération des caractères, donc nous ne devons pas gaspiller dans les cas où il n'y a pas besoin d'une manipulation de chaîne sur le résultat (disons que nous allions écrire les caractères pour les afficher ensuite, ou manipulation par char).

Un exemple cas pour quelque chose où nous voulions également convertir l et l à l et L, mais n'a pas eu d'autres préoccupations spécialisées pourraient utiliser:

private static char NormaliseLWithStroke(char c) 
{ 
    switch(c) 
    { 
    case 'ł': 
     return 'l'; 
    case 'Ł': 
     return 'L'; 
    default: 
     return c; 
    } 
} 

utilisant cette option avec les méthodes ci-dessus combinera pour enlever la coup dans ce cas, avec les diacritiques décomposables.

+0

Il y a quelques problèmes de syntaxe, pourriez-vous les corriger? Votre réponse fonctionne et est très éclairante. Je vous remercie. – BrunoLM

+0

Bon vous êtes Bruno, quelques bits faux en raison d'écrire directement comme une réponse plutôt que de copier à partir d'un éditeur de code. Doit être correct maintenant. –

+1

+1 Cela semble fonctionner mais je ne suis pas.Pourriez-vous expliquer customFolding? – Paparazzi

15
public string RemoveDiacritics(string input) 
{ 
    string stFormD = input.Normalize(NormalizationForm.FormD); 
    int len = stFormD.Length; 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < len; i++) 
    { 
     System.Globalization.UnicodeCategory uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stFormD[i]); 
     if (uc != System.Globalization.UnicodeCategory.NonSpacingMark) 
     { 
      sb.Append(stFormD[i]); 
     } 
    } 
    return (sb.ToString().Normalize(NormalizationForm.FormC)); 
} 
+1

Pourquoi autoriser SpacingCombiningMark et EnclosingMark? –

+0

Comme précédemment mentionné par Karaszi, son seul exemple de comment cela peut être fait. Bruno n'a pas précisé les exigences exactes. – cichy

+0

@cichy string n'a pas de méthode Normalize!? – onmyway133

Questions connexes