2010-09-22 21 views
13

Duplicar posible:
How do I remove diacritics (accents) from a string in .NET?¿Cómo puedo eliminar acentos en una cadena?

tengo la siguiente cadena

áéíóú 

cual necesito para convertirlo en

aeiou 

¿Cómo puedo lograrlo? (No necesito comparar, necesito la nueva cadena de ahorrar)


No

un duplicado de How do I remove diacritics (accents) from a string in .NET?. La respuesta aceptada allí no explica nada y es por eso que la he "reabierto".

+0

Maldición, quiero rescindir mi reapertura, definitivamente es un duplicado. @BrunoLM si no te gusta la respuesta, es mejor ponerle una recompensa que pedir a un duplicado –

Respuesta

21

Depende de los requisitos. Para la mayoría de los usos, entonces normalizar a NFD y luego filtrar todos los caracteres combinados funcionará. En algunos casos, la normalización a NFKD es más apropiada (si también desea eliminar algunas distinciones adicionales entre caracteres).

Algunas otras distinciones no se verán atrapadas por este, especialmente los caracteres latinos acariciados. Tampoco hay una forma clara y específica para algunos (¿se debe considerar que es equivalente a l o w?), Por lo que es posible que deba personalizarla más allá de esto.

También hay algunos casos en los que NFD y NFKD no funcionan del modo esperado, para permitir la coherencia entre las versiones de Unicode.

Por lo tanto:

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

aquí hay un valor predeterminado para los casos problemáticos mencionados anteriormente, que simplemente los ignora. También hemos dividido construir una cadena para que no se genere la enumeración de caracteres, por lo que no debemos desperdiciar en los casos donde no hay necesidad de manipulación de cadenas en el resultado (digamos que íbamos a escribir los caracteres a la salida siguiente, o hacer un char adicional manipulación por charla).

un caso de ejemplo de algo donde queríamos convertir también L y L a L y L, pero no tenía otras preocupaciones especializadas podrían utilizar:

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

El uso de este con los métodos anteriores se combinan para eliminar el accidente cerebrovascular en este caso, junto con los signos diagonales descomponibles.

+0

Existen algunos problemas de sintaxis, ¿podría solucionarlos? Tu respuesta funciona y es muy esclarecedora. Gracias. – BrunoLM

+0

Bien, usted es Bruno, algunos errores debido a escribir directamente como respuesta en lugar de copiar desde un editor de código. Debería ser correcto ahora –

+1

+1 Parece que funciona, pero no sigo.¿Podrías explicar 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

¿Por qué permitir SpacingCombiningMark y EnclosingMark? –

+0

Según lo mencionado anteriormente por Karaszi, es el único ejemplo de cómo se puede hacer. Bruno no especificó los requisitos exactos. – cichy

+0

@cichy string no tiene método Normalize! – onmyway133

Cuestiones relacionadas