6

問題:外部システムからの2つの固定幅の文字列があります。最初の文字には基本文字(azなど)が含まれ、2番目の文字(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#)を使用して、10進値を計算してみましたが、結果はありませんでした。また、グーグルは実際に何かを思いついたわけではありません。

4

4 に答える 4

5

発音区別符号の範囲を組み合わせたUnicodeから、発音区別符号を適切なユニコード値に変換します。

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

次に、charとその発音区別符号を一緒に叩きます。たとえば、e-acuteの場合、U + 0065="e"およびU+0301=acuteです。

  String s = "\u0065\u0301";

それで:

  string normalisedString = s.Normalize();

2つを組み合わせて新しい文字列にします。

于 2010-03-09T12:57:39.160 に答える
1

問題は、指定されたダイアクリットを明示的に解析する必要があることです。これにより、二重点が単独で存在しないため、この場合は二重引用符が使用されます。したがって、問題を解決するために、必要な各ケースを実装する機会は他にありません。

手がかりを得るための出発点はここにあります...

    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はすでに.Net4に実装されていますが、3.5で取得するには、次のコードが必要です(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);
    }
}
于 2010-03-09T12:41:22.930 に答える
1

ルックアップテーブルを使用する以外に簡単な解決策を見つけることができません。

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<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;
    }
}
于 2010-03-09T12:47:58.703 に答える
0

C#またはその標準ライブラリはわかりませんが、別のアプローチの1つは、既存の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-> &Aring;u + "->&uuml;などです。

その後、htmlエンティティを解析できる場合は、ホームフリーであり、文字セット間で移植可能である必要があります。

于 2010-07-08T12:16:05.710 に答える