2010-03-09 16 views
6

El problema: Tengo dos cadenas de ancho fijo desde un sistema externo. El primero contiene los caracteres base (como a-z), el segundo (MAYO) contiene signos diacríticos que se anexarán a la primera cadena para crear los caracteres reales.Convierte dos caracteres ascii en su representación Ascii extendida de un carácter 'correspondiente'

string asciibase = "Dutch has funny chars: a,e,u"; 
string diacrits = "      ' \" \""; 

//no clue what to do 

string result = "Dutch has funny chars: á,ë,ü"; 

podría escribir una búsqueda masiva y reemplazar para todos los caracteres + diferentes diacríticos, pero esperaba algo un poco más elegante.

¿Alguien tiene una idea de cómo solucionar este problema? Lo intenté con el cálculo de los valores decimales, utilizando una cadena.Normalizar (C#) pero sin resultados. Además, Google realmente no apareció con algo.

+0

Usted está buscando lo contrario de la cadena. Normalizar, me temo que no hay un método integrado para obtener lo que quiere ... –

+0

Creo que está después de la normalización, es solo que sus signos diacríticos no son los que combinan no funciona –

Respuesta

1

no puedo encontrar una solución fácil, excepto utilizando tablas de búsqueda:

public void TestMethod1() 
{ 
    string asciibase = "Dutch has funny chars: a,e,u"; 
    string diacrits = "      ' \" \""; 
    var merged = DiacritMerger.Merge(asciibase, diacrits); 
} 

[EDIT: simplificado código después de sugerencias en las respuestas de @JonB y @Oliver]

public class DiacritMerger 
{ 
    static readonly Dictionary<char, char> _lookup = new Dictionary<char, char> 
         { 
          {'\'', '\u0301'}, 
          {'"', '\u0308'} 
         }; 

    public static string Merge(string asciiBase, string diacrits) 
    { 
     var combined = asciiBase.Zip(diacrits, (ascii, diacrit) => DiacritVersion(diacrit, ascii)); 
     return new string(combined.ToArray()); 
    } 

    private static char DiacritVersion(char diacrit, char character) 
    { 
     char combine; 
     return _lookup.TryGetValue(diacrit, out combine) ? new string(new [] {character, combine}).Normalize()[0] : character; 
    } 
} 
1

El problema es que los diacrits especificados deben analizarse explícitamente, porque los puntos dobles no existen únicos y, por lo tanto, las comillas dobles se usan para este caso. Entonces, para lograr su problema, no tiene otra oportunidad que implementar cada caso necesario.

Aquí es un punto de partida para conseguir una pista ...

public SomeFunction() 
    { 
     string asciiChars = "Dutch has funny chars: a,e,u"; 
     string diacrits = "      ' \" \""; 

     var combinedChars = asciiChars.Zip(diacrits, (ascii, diacrit) => 
     { 
      return CombineChars(ascii, diacrit); 
     }); 

     var Result = new String(combinedChars.ToArray()); 
    } 

    private char CombineChars(char ascii, char diacrit) 
    { 
     switch (diacrit) 
     { 
      case '"': 
       return AddDoublePoints(ascii); 
      case '\'': 
       return AddAccent(ascii); 
      default: 
       return ascii; 
     } 
    } 

    private char AddDoublePoints(char ascii) 
    { 
     switch (ascii) 
     { 
      case 'a': 
       return 'ä'; 
      case 'o': 
       return 'ö'; 
      case 'u': 
       return 'ü'; 
      default: 
       return ascii; 
     } 
    } 

    private char AddAccent(char ascii) 
    { 
     switch (ascii) 
     { 
      case 'a': 
       return 'á'; 
      case 'o': 
       return 'ó'; 
      default: 
       return ascii; 
     } 
    } 
} 

El IEnumerable.Zip ya está implemented in .Net 4, pero para conseguir que en el punto 3.5 que necesitará este código (taken from Eric Lippert):

public static class IEnumerableExtension 
{ 
    public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> 
     (this IEnumerable<TFirst> first, 
     IEnumerable<TSecond> second, 
     Func<TFirst, TSecond, TResult> resultSelector) 
    { 
     if (first == null) throw new ArgumentNullException("first"); 
     if (second == null) throw new ArgumentNullException("second"); 
     if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 
     return ZipIterator(first, second, resultSelector); 
    } 

    private static IEnumerable<TResult> ZipIterator<TFirst, TSecond, TResult> 
     (IEnumerable<TFirst> first, 
     IEnumerable<TSecond> second, 
     Func<TFirst, TSecond, TResult> resultSelector) 
    { 
     using (IEnumerator<TFirst> e1 = first.GetEnumerator()) 
     using (IEnumerator<TSecond> e2 = second.GetEnumerator()) 
      while (e1.MoveNext() && e2.MoveNext()) 
       yield return resultSelector(e1.Current, e2.Current); 
    } 
} 
+0

La solución que está dando es la única salida fácil que encontré, pero también es la que mata más cerebros ... Lo guardo para último recurso;) –

+1

Después de leer las otras respuestas, posiblemente encuentre una buena solución combinando todos ellos (como lo hizo Mikael en su publicación) de alguna manera. – Oliver

4

convertir los signos diacríticos para valores Unicode adecuados desde el Unicode en combinación diacrítica van:

http://www.unicode.org/charts/PDF/U0300.pdf

A continuación, da una bofetada al char y su signo diacrítico juntos, por ejemplo para e-aguda, U + 0065 = "e" y U + 0301 = agudo.

String s = "\u0065\u0301"; 

continuación:

string normalisedString = s.Normalize(); 

combinará los dos en una nueva cadena.

0

No sé C#, o sus bibliotecas estándar, pero un enfoque alternativo podría ser utilizar algo así como un analizador/procesador de entidades de caracteres HTML/SGML/XML existente, o si realmente va a presentarlo a un navegador, nada!

pseudo código:

for(i=0; i < strlen(either_string); i++) { 
    if isspace(diacrits[i]) { 
    output(asciibase[i]); 
    }else{ 
    output("&"); 
    output(asciibase[i]); 
    switch (diacrits[i]) { 
     case '"' : output "uml"; break; 
     case '^' : output "circ"; break; 
     case '~' : output "tilde"; break; 
     case 'o' : output "ring"; break; 
     ... and so on for each "code" in the diacrits modifier 
     ... (for acute, grave, cedil, lig, ...) 
    } 
    output(";"); 
    } 
} 

Por lo tanto, A + o ->&Aring;, u + " ->&uuml; y así sucesivamente.

Si puede analizar entidades html, entonces debería estar en casa libre, e incluso portátil entre conjuntos de caracteres!

Cuestiones relacionadas