将两个ascii字符转换为它们的“对应”一个字符扩展ascii表示

问题:我有两个来自外部系统的固定宽度字符串。 第一个包含基本字符(如az),第二个(MAY)包含要附加到第一个字符串以创建实际字符的变音符号。

string asciibase = "Dutch has funny chars: a,e,u"; string diacrits = " ' \" \""; //no clue what to do string result = "Dutch has funny chars: á,ë,ü"; 

我可以写一个大规模的搜索并替换所有字符+不同的变音符号,但希望有更优雅的东西。

有人知道如何解决这个问题? 尝试计算小数值,使用string.Normalize(c#),但没有结果。 谷歌也没有真正想出办法。

除了使用查找表之外,我找不到简单的解决方案:

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

[编辑:在@JonB和@Oliver的答案中提出建议后的简化代码]

 public class DiacritMerger { static readonly Dictionary _lookup = new Dictionary { {'\'', '\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; } } 

将变音符号转换为Unicode组合变音符号范围的合适unicode值:

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

然后拍打炭及其变音符号,例如e-acute,U + 0065 =“e”,U + 0301 =急性。

  String s = "\u0065\u0301"; 

然后:

  string normalisedString = s.Normalize(); 

将两者合并为一个新的字符串。

问题是,必须显式解析指定的diacrits,导致双点不存在于sole,因此双引号用于这种情况。 因此,为了解决您的问题,您没有任何其他机会来实施每个必要的案例。

这是获得线索的起点……

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

IEnumerable.Zip已经在.Net 4中实现了 ,但要在3.5中获得它,你需要这个代码( 取自Eric Lippert ):

 public static class IEnumerableExtension { public static IEnumerable Zip (this IEnumerable first, IEnumerable second, Func 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 ZipIterator (IEnumerable first, IEnumerable second, Func resultSelector) { using (IEnumerator e1 = first.GetEnumerator()) using (IEnumerator e2 = second.GetEnumerator()) while (e1.MoveNext() && e2.MoveNext()) yield return resultSelector(e1.Current, e2.Current); } } 

我不知道C#或其标准库,但是一种替代方法可能是利用现有的HTML / SGML / XML字符实体解析器/渲染器之类的东西,或者如果你真的要将它呈现给浏览器, 那就什么都不是

伪代码:

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

因此, A + o - > Åu + " - > ü依此类推。

如果你可以解析html实体,那么你应该在家里免费,甚至可以在charsets之间移植!