2010-09-22 21 views
13

Mögliche Duplizieren:
How do I remove diacritics (accents) from a string in .NET?Wie kann ich Akzente an einer Zeichenfolge entfernen?

Ich habe die folgende Zeichenfolge

áéíóú 

, die ich es

konvertieren müssen
aeiou 

Wie kann ich es erreichen? (Ich brauche nicht zu vergleichen, ich brauche die neue Zeichenfolge zu speichern)


kein Duplikat von How do I remove diacritics (accents) from a string in .NET?. Die angenommene Antwort erklärt nichts und deshalb habe ich sie "wieder geöffnet".

+0

Verdammt, möchte meine Wiedereröffnung rückgängig machen - es ist definitiv ein Duplikat. @BrunoLM, wenn Sie die Antwort nicht mögen, ist es besser, ein Kopfgeld darauf zu setzen, dass eine dup –

Antwort

21

Es hängt von den Anforderungen ab. Für die meisten Anwendungen reicht es aus, auf NFD zu normalisieren und dann alle kombinierenden Zeichen herauszufiltern. In einigen Fällen ist eine Normalisierung auf NFKD geeigneter (wenn Sie auch weitere Unterscheidungen zwischen Zeichen entfernen möchten).

Einige andere Unterscheidungen werden dadurch nicht erfasst, insbesondere gestrichene lateinische Zeichen. Es gibt auch keine eindeutige, nicht länderspezifische Methode für einige (sollte als gleichwertig mit l oder w betrachtet werden), so dass Sie möglicherweise darüber hinaus anpassen müssen.

Es gibt auch einige Fälle, in denen NFD und NFKD nicht ganz wie erwartet funktionieren, um Konsistenz zwischen Unicode-Versionen zu ermöglichen.

Daraus folgt:

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

Hier haben wir einen Standard für die Problemfälle oben erwähnt, die sie nur ignoriert. Wir haben auch den Aufbau einer Zeichenkette vom Erzeugen der Aufzählung von Zeichen getrennt, so dass wir keine Verschwendung in Fällen brauchen, in denen keine String-Manipulation auf das Ergebnis notwendig ist (sagen wir, würden wir die Zeichen als nächstes ausgeben oder ein weiteres Zeichen machen) -von-Char-Manipulation).

Ein Beispielfall für etwas, wo wir L und L bis L und L, hatte aber keine andere spezialisierte Bedenken nutzen könnten, um auch konvertieren wollte:

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

Mit diesem mit den obigen Verfahren die entfernen kombinieren Schlag in diesem Fall zusammen mit den zerlegbaren diakritischen Zeichen.

+0

Es gibt einige Syntaxprobleme, könnten Sie sie beheben? Ihre Antwort funktioniert und ist sehr aufschlussreich. Vielen Dank. – BrunoLM

+0

Richtig, du bist Bruno, ein paar Fehler, weil du direkt als Antwort geschrieben hast und nicht aus einem Code-Editor kopiert hast. Sollte jetzt stimmen. –

+1

+1 Es scheint zu funktionieren, aber ich folge nicht.Würden Sie CustomFolding erklären? – 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

Warum SpacingCombiningMark und EnclosingMark? –

+0

Wie von Karaszi oben erwähnt, ist es das einzige Beispiel dafür, wie es gemacht werden kann. Bruno hat keine genauen Anforderungen angegeben. – cichy

+0

@cichy String hat keine Normalize-Methode!? – onmyway133

Verwandte Themen